LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

learn_slam

2022/7/21

SLAM笔记

学习方式是看高翔的视觉SLAM十四讲

学习视频:https://www.bilibili.com/video/BV16t411g7FR

学习参考代码:https://github.com/gaoxiang12/slambook

学习实现代码:https://github.com/bonbon-rj/learn_slam


CH1-CH2:初识SLAM

测量深度

单目:移动相机产生深度

双目:通过两个摄像头视差产生深度

深度相机(RGBD):通过物理方法得到深度(受光照影响大)


视觉SLAM框架

1.前端(VO)

2.后端(Optimization)

3.回环检测(Loop Closing)

4.建图(Mapping)


CH3:三维空间刚体运动

内积外积

向量内积,结果是个值,表示两个向量的相似程度,结果与点积一致

a,b=abcosθ=i=13aibi=ab=aTb\langle a, b \rangle = \vert a\vert \vert b \vert cos\theta =\sum_{i=1}^{3}a_ib_i= a \cdot b = a^T b

向量外积,结果是个向量,符合右手螺旋定则,结果与叉乘一致

ab=a×b=[a2b3a3b2,a3b1a1b3,a1b2a2b1]T=[0a3a2a30a1a2a10][b1b2b3]a \otimes b = a \times b = [a_2b_3-a_3b_2,a_3b_1-a_1b_3,a_1b_2-a_2b_1]^T= \begin{bmatrix} 0 & -a_3 & a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0 \end{bmatrix} \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix}

特殊正交群:SO(3)={RR3×3RRT=I,det(R)=1}SO(3)=\{R \in R^{3 \times 3}|RR^T=I,det(R)=1 \},对应旋转矩阵

特殊欧式群:SE(3)={T=[Rt01],RSO(3),tR3}SE(3)=\{T=\begin{bmatrix}R&t\\0&1 \end{bmatrix},R\in SO(3),t \in R^3\},对应齐次变换矩阵

齐次变换矩阵求逆:T1=[RTRTt01]T^{-1}=\begin{bmatrix} R^T &-R^Tt \\ 0 & 1\end{bmatrix}

一般将TWT_W表示为世界坐标系,将TRT_R表示为机器人坐标系,用TRWT_{RW}TWRT_{WR}表示机器人位姿


旋转向量

向量aa沿着旋转轴nn旋转角度θ\theta到向量bb

w=θnw=\theta n称为角轴或旋转向量,nn为方向向量

角轴转化为旋转矩阵:R=cosθI+(1cosθ)nnT+sinθn^R=cos\theta I+(1-cos\theta)nn^T+sin\theta \hat n,罗德里格斯公式

旋转矩阵到轴角:θ=arccostr(R)12\theta = arccos\frac{tr(R)-1}{2}Rn=nRn=n,结合特征值的定义Ax=λxAx=\lambda xnnRR特征值为1的特征向量


欧拉角

绕着自身坐标系旋转

Z轴:偏航,X轴:翻滚,Y轴:俯仰

存在万向锁问题:

比如在ZYX欧拉角中,若pitch为正负90°时,第一次和第三次旋转是绕同一个轴,丢失一个自由度


四元数

在复变函数中,复数乘以ii,可以表示复数逆时针旋转90°

进一步地,单位圆上的复数可以表示二维平面的旋转

四元数q=q0+q1i+q2j+q3kq=q_0+q_1i+q_2j+q_3k有三个虚部,可以表示三维空间的旋转

四元数常表示成一个实部和虚部向量 q=[s,v],s=q0R,v=[q1,q2,q3]TR3q=[s,v],s=q_0 \in R,v=[q_1,q_2,q_3]^T \in R^3

虚部之间的关系,i2=j2=k2=1i^2=j^2=k^2=-1ij=k,jk=i,ki=jij=k,jk=i,ki=j

可以将ijkijk理解成右手系的xyzxyz,用叉乘理解上述关系


四元数运算

假设qa=[sa,va]=sa+xai+yaj+zakq_a = [s_a,v_a]=s_a+x_ai+y_aj+z_akqb=[sb,vb]=sb+xbi+ybj+zbkq_b=[s_b,v_b]=s_b+x_bi+y_bj+z_bk,则有

加减:qa±qb=[sa±sb,va±vb]q_a \pm q_b=[s_a \pm s_b,v_a \pm v_b]

乘法:qaqb=[sasbvaTvb,savb+sbva+va×vb]q_aq_b=[s_as_b-v_a^Tv_b,s_av_b+s_bv_a+v_a \times v_b]

共轭:qa=[sa,va]q_a^*=[s_a,-v_a]

模长(范数):qa=sa2+xa2+ya2+za2\vert \vert q_a\vert \vert=\sqrt{s_a^2+x_a^2+y_a^2+z_a^2}

逆:q1=qq2q^{-1}=\frac{q^*}{\vert \vert q\vert \vert^2}

数乘:kqa=[ksa,kva]kq_a=[ks_a,kv_a]

点乘:qaqb=sasb+xaxbi+yaybj+zazbkq_a \cdot q_b=s_as_b+x_ax_bi+y_ay_bj+z_az_bk


四元数与角轴的关系

角轴到四元数:q=[cosθ2,nxsinθ2,nysinθ2,nzsinθ2]Tq=[cos\frac{\theta}{2},n_xsin\frac{\theta}{2},n_ysin\frac{\theta}{2},n_zsin\frac{\theta}{2}]^T

四元数到角轴:θ=2arccosq0,[nx,ny,nz]T=[q1,q2,q3]Tsinθ2\theta=2arccosq_0,[n_x,n_y,n_z]^T=\frac{[q_1,q_2,q_3]^T}{sin\frac{\theta}{2}}


四元数旋转空间点

假设p0=(x,y,z)p_0=(x,y,z),则我们设p=[0,x,y,z]=[0,v]p=[0,x,y,z]=[0,v]

则经过四元数qq旋转后p=qpq1p' = qpq^{-1}

四元数相比于角轴、欧拉角的优点:紧凑、无奇异性


旋转

绕x轴旋转α\alpha角:Rot(x,α)=[1000CαSα0SαCα]Rot(\vec{x},\alpha)=\begin{bmatrix} 1 & 0 & 0 \\ 0 & C\alpha & -S\alpha \\ 0 & S\alpha & C\alpha\end{bmatrix}

绕y轴旋转β\beta角:Rot(y,β)=[Cβ0Sβ010Sβ0Cβ]Rot(\vec{y},\beta)=\begin{bmatrix} C\beta & 0 & S\beta \\ 0 & 1 & 0 \\ -S\beta & 0 & C\beta\end{bmatrix}

绕z轴旋转γ\gamma角:Rot(z,γ)=[CγSγ0SγCγ0001]Rot(\vec{z},\gamma)=\begin{bmatrix} C\gamma & -S\gamma & 0 \\ S\gamma & C\gamma & 0 \\ 0 & 0 & 1\end{bmatrix}


代码实现细项

Eigen安装
sudo apt-get install libeigen3-dev # 安装
whereis eigen3 # 查看库位置 显示/usr/include/eigen3
locate eigen3 | grep include # 模糊搜索 表示含有eigen3的所有包含include的路径

CH4:李群与李代数

表示刚体在三维的运动后,我们还要对其进行估计和优化

角轴是旋转矩阵对应的李代数,相对于旋转矩阵,优化时无约束

且引出李代数是为了进行求导等操作


群是一种集合加上一种运算的代数结构

记集合为AA,运算为\cdot,那么满足以下性质时,称(A,)(A ,\cdot)为群

1.封闭性:a1,a2A,a1a2A\forall a_1,a_2 \in A,a_1 \cdot a_2 \in A,概括就是在集合上运算的结果还在集合内

2.结合律:a1,a2,a3A,(a1a2)a3=a1(a2a3)\forall a_1,a_2,a_3 \in A,(a_1 \cdot a_2) \cdot a_3=a_1 \cdot (a_2 \cdot a_3)

3.幺元:a0A,aA,a0a=aa0=a\exists a_0 \in A, \forall a \in A,a_0 \cdot a = a \cdot a_0 = a,其中a0a_0为幺元

辅助理解就是 运算为加时a0a_0可以是0,运算为乘时a0a_0可以是1

4.逆:aA,a1A,aa1=a0\forall a \in A,\exists a^{-1} \in A, a \cdot a^{-1} = a_0,任意元素存在逆,且逆与元素运算结果为幺元


GL(n)GL(n):一般线性群,指n×nn \times n的可逆矩阵,对矩阵乘法成群

SO(n)SO(n):特殊正交群,由旋转矩阵和矩阵乘法构成的群,或称旋转矩阵群

SE(n)SE(n):特殊欧式群,由齐次变换矩阵和矩阵乘法构成的群,或称变换矩阵群


李群

GG是一个拓扑群,同时是一个微分流形。若GG作为群的群乘法与逆映射都是光滑的,则GG称为李群

1.具有连续(光滑)性质的群

2.既是群也是流形

3.一个刚体在空间中能连续地运动

SO(3)SO(3)SE(3)SE(3)都是李群


李代数

李代数由一个集合VV,一个数域FF和一个二元运算[,][,]组成

如果满足以下性质,则称(V,F,[,])(V,F,[,])为一个李代数,记作gg

1.封闭性 2.双线性 3.自反性 4.雅克比等价

其中二元运算[,][,]被称为李括号,表达两个元素的差异(自反性)


在李代数so(3)={ϕR3,ϕ^R3×3}so(3)=\{ {\phi \in R^3,\hat \phi \in R^{3 \times 3} } \}

李括号为[ϕ1,ϕ2]=(ϕ^1ϕ^2ϕ^2ϕ^1)ˇ[\phi_1,\phi_2]=(\hat \phi_1 \hat \phi_2 - \hat \phi_2 \hat \phi_1)\check{}

其中 ^\hat{} 运算如下, ˇ\check{} 是反运算

假设三维向量a=[a1a2a3]a = \begin{bmatrix} a_1\\a_2\\a_3 \end{bmatrix},则a^=A=[0a3a2a30a1a2a10]\hat a = A = \begin{bmatrix} 0&-a_3&a_2\\a_3& 0&-a_1\\-a_2 & a_1 & 0 \end{bmatrix}

AA称为向量aa的反对称矩阵


在李代数se(3)={ξ=[pϕ]R6,ρR3,ϕso(3),ξ^=[ϕ^ρ0T0]R4×4}se(3)=\{ \xi = \begin{bmatrix} p \\ \phi\end{bmatrix} \in R^6,\rho \in R^3,\phi \in so(3), \hat \xi = \begin{bmatrix} \hat \phi &\rho \\ 0^T & 0\end{bmatrix} \in R^{4 \times 4}\}

李括号为[ξ1,ξ2]=(ξ^1ξ^2ξ^2ξ^1)ˇ[\xi_1,\xi_2]=(\hat \xi_1 \hat \xi_2 -\hat \xi_2 \hat \xi_1)\check {}

其中 ^\hat{} 运算如下, ˇ\check{} 是反运算

假设六维向量a=[ρ1ρ2ρ3ϕ1ϕ2ϕ3]=[ρϕ]a =\begin{bmatrix} \rho_1 \\ \rho_2 \\ \rho_3 \\ \phi_1 \\ \phi_2 \\ \phi_3\end{bmatrix}=\begin{bmatrix} \rho \\ \phi\end{bmatrix},则a^=[0ϕ3ϕ2ρ1ϕ30ϕ1ρ2ϕ2ϕ10ρ30000]\hat a=\begin{bmatrix} 0&-\phi_3&\phi_2 &\rho_1\\\phi_3& 0&-\phi_1&\rho_2\\-\phi_2 & \phi_1 & 0 &\rho_3 \\ 0&0&0&0\end{bmatrix}


李群与李代数

每个李代数都有与之对应的李群,位于向量空间,实际是李群单位元处的正切空间

SO(3)SO(3)对应的李代数为so(3)so(3)SE(3)SE(3)对应的李代数为se(3)se(3)


李代数可以通过指数映射转换为李群,李群也可以通过对数映射转换为李代数

李群与李代数的指数映射关系是通过正交性且连续然后求导化简而得

指数映射关系化简是使用了泰勒展开加一些反对称矩阵高次规律进行化简而得


例如对于SO(3)SO(3)R=exp(θa^)=cosθI+(1cosθ)aaT+sinθa^R = exp(\theta \hat a)=cos\theta I+(1-cos\theta)aa^T+sin\theta \hat a,李代数so(3)so(3)其实就是角轴


具体SO(3)SO(3)so(3)so(3)的转换以及SE(3)SE(3)se(3)se(3)的转换如下图(图源于视频链接)


我再自己梳理一遍:

SO(3)SO(3)3×33 \times 3矩阵RRso(3)so(3)3×13 \times 1的向量ϕ=θn=[ϕ1ϕ2ϕ3]\phi=\theta n=\begin{bmatrix} \phi_1 \\ \phi_2 \\ \phi_3\end{bmatrix}

SO(3)SO(3)so(3)so(3)θ=arccostr(R)12\theta = arccos \frac{tr(R)-1}{2}Rn=nRn=n

so(3)so(3)SO(3)SO(3)R=cosθI+(1cosθ)nnT+sinθn^R=cos\theta I+(1-cos\theta)nn^T+sin\theta \hat n

SE(3)SE(3)4×44 \times 4矩阵T=[Rt01]T=\begin{bmatrix} R &t \\ 0 & 1\end{bmatrix}se(3)se(3)6×16 \times 1的向量ξ=[ρ1ρ2ρ3ϕ1ϕ2ϕ3]=[ρnθ]=[ρϕ]\xi =\begin{bmatrix} \rho_1 \\ \rho_2 \\ \rho_3 \\ \phi_1 \\ \phi_2 \\ \phi_3\end{bmatrix}=\begin{bmatrix} \rho \\ n\theta\end{bmatrix}=\begin{bmatrix} \rho \\ \phi\end{bmatrix}

其中有雅克比J=sinθθI+(1sinθθ)nnT+1cosθθn^J=\frac{sin\theta}{\theta}I+(1-\frac{sin\theta}{\theta})nn^T+\frac{1-cos\theta}{\theta}\hat n

SE(3)SE(3)se(3)se(3)θ=arccostr(R)12\theta = arccos \frac{tr(R)-1}{2}Rn=nRn=nt=Jρt = J\rho

se(3)se(3)SE(3)SE(3)T=[cosθI+(1cosθ)nnT+sinθn^Jρ01]T =\begin{bmatrix} cos\theta I+(1-cos\theta)nn^T+sin\theta \hat n &J\rho \\ 0 & 1\end{bmatrix}

对于三维向量a=[a1a2a3]a=\begin{bmatrix} a_1\\a_2\\a_3 \end{bmatrix}a^=[0a3a2a30a1a2a10]\hat a = \begin{bmatrix} 0&-a_3&a_2\\a_3& 0&-a_1\\-a_2 & a_1 & 0 \end{bmatrix}

对于六维向量a=[a1a2a3b1b2b3]=[ab]a=\begin{bmatrix} a_1\\a_2\\a_3\\b_1\\b_2\\b_3 \end{bmatrix}=\begin{bmatrix} a\\b \end{bmatrix}a^=[b^a00]\hat a=\begin{bmatrix} \hat b &a \\ 0 & 0\end{bmatrix},这里a,ba,b位置可能颠倒,在这里aa代表平移分量


李代数求导

从李群到李代数,是为了可以求导等操作,因为在李群上做加法不封闭

一般情况下,在李代数中做加法与李群上做乘法不等价,由BCH公式可证:

exp(ϕ^1)exp(ϕ^2)exp((ϕ1+ϕ2)^)exp(\hat \phi_1)exp(\hat \phi_2) \neq exp((\phi_1+\phi_2)\hat{})

特别地,当其中有一个小量时,可以近似获得:(加粗括号是取下三角部分)

(ln(exp(ϕ^1)exp(ϕ^2)))ˇ{Jl(ϕ2)1ϕ1+ϕ2,ifϕ1issmallJr(ϕ1)1ϕ2+ϕ1,ifϕ2issmall(ln(exp(\hat \phi_1)exp(\hat \phi_2)))\check {} \approx \left\{\begin{matrix} J_l(\phi_2)^{-1}\phi_1+\phi_2 ,if \, \, \phi_1 \, \, is \,\,small \\ J_r(\phi_1)^{-1}\phi_2+\phi_1 ,if \, \, \phi_2 \, \, is \,\,small \end{matrix}\right.

其中JlJ_l为左乘雅克比,JrJ_r为右乘雅克比

Jl=sinθθI+(1sinθθ)nnT+1cosθθn^J_l = \frac{sin\theta}{\theta}I+(1-\frac{sin\theta}{\theta})nn^T+\frac{1-cos\theta}{\theta}\hat n

Jr(ϕ)=Jl(ϕ)J_r(\phi)=J_l(-\phi)

左乘雅克比的逆为:

Jl1=θ2cotθ2I+(1θ2cotθ2)nnTθ2n^J_l^{-1} = \frac{\theta}{2}cot\frac{\theta}{2}I+(1-\frac{\theta}{2}cot\frac{\theta}{2})nn^T-\frac{\theta}{2}\hat n

SO(3)SO(3)so(3)so(3)上,以左乘李代数为例

李群左乘小量,有:

exp((Δϕ)^)exp(ϕ^)=exp((ϕ+Jl1(ϕ)Δϕ)^),exp((\Delta \phi)\hat{})exp( \phi \hat{})=exp({(}\phi+J_l^{-1}(\phi)\Delta\phi)\hat{}),

李代数加小量,有:

exp((ϕ+Δϕ)^)=exp((JlΔϕ)^)exp(ϕ^)=exp(ϕ^)exp((JrΔϕ)^)exp((\phi+\Delta\phi )\hat {}) =exp((J_l \Delta\phi)\hat{})exp( \phi\hat{})=exp( \phi\hat{})exp((J_r \Delta\phi)\hat{})

有了上述前提,我们可以求解李代数上的导数

如果点pp经过旋转RR后的为点pp',求点pp'关于RR的导数

可以考虑对RR对应的李代数ϕ\phi加上小量Δ\Delta,求pp'相对于Δ\Delta的变化率(导数模型)

可以考虑对RR乘以一个小量Δ\Delta,求pp'相对于Δ\Delta的李代数的变化率(扰动模型)


对于S0(3)S0(3)δ\delta为小量,pp为变换点,RR为旋转矩阵,JlJ_l为对应的左乘雅克比

导数模型:(exp(ϕ^)p)δ=(Rp)^Jl\frac{\partial( exp(\hat \phi)p)}{\partial \delta}=-(Rp)\hat{}J_l (不常用)

扰动模型:Rpδ=(Rp)^\frac{\partial Rp}{\partial \delta}=-(Rp)\hat{}


对于SE(3)SE(3)ξ\xi为小量,pp为变换点,T=[Rt01]T=\begin{bmatrix} R & t \\ 0 &1\end{bmatrix}

扰动模型:(Tp)ξ=[I(Rp+t)^0T0T]\frac{\partial (Tp)}{\partial \xi} =\begin{bmatrix} I & -(Rp+t) \hat{} \\ 0^T & 0 ^T \end{bmatrix}


代码实现细项

Sophus安装
git clone https://github.com/strasdat/Sophus.git
cd Sophus
mkdir build
cd build
cmake ..
make
sudo make install # 实现效果为 把头文件放在了include目录下,把库文件放在了lib目录下

Sophus注意事项

可能是Sophus版本不同,我的使用与视频中不一致

需要在CMakeLists中需要添加一句才不会报错

# 解决 fatal error: fmt/core.h: 没有那个文件或目录
target_link_libraries(${PROJECT_NAME} Sophus::Sophus) 

然后代码编写也是很多不相同,不一一列举。


CH5:相机与图像

成像原理

观测方程由相机观测模型组成

假设一点相对于光心的坐标为(X,Y,Z)(X,Y,Z)(相机坐标系),在像素平面在的坐标为(X,Y)(X',Y'),单位mm

小孔成像原理,并将图像翻转到前面(倒像转正像),可得

X=fXZX' = f \frac{X}{Z}

Y=fYZY' = f\frac{Y}{Z}

假设像素平面像素坐标为(u,v)(u,v)(像素坐标系),存在以下关系式

u=αX+cxu=\alpha X'+c_x

v=βY+cyv=\beta Y'+c_y

α,β\alpha,\beta是放大系数,将单位为mm转换为像素

cx,cyc_x,c_y为偏置,因为像素坐标系的原点不在光心

联立可得

u=αfXZ+cx=fxXZ+cxu = \alpha f \frac{X}{Z}+c_x = f_x \frac{X}{Z}+c_x

v=βfYZ+cy=fyYZ+cyv = \beta f \frac{Y}{Z}+c_y = f_y \frac{Y}{Z}+c_y

写成矩阵为

Z[uv1]=[fx0cx0fycy001][XYZ]=KPZ\begin{bmatrix} u \\ v \\ 1\end{bmatrix} =\begin{bmatrix} f_x & 0 & c_x \\ 0 &f_y&c_y \\0&0& 1\end{bmatrix}\begin{bmatrix} X \\ Y \\ Z\end{bmatrix} = KP

其中KK为内参矩阵,内参矩阵一般是固定的,标定获得

但是要注意,如果缩放图像,内参是改变了


外参

一般我们已知的是世界坐标系下的一点的坐标PwP_w

这一点在世界坐标系和相机坐标系之间存在变换P=RPw+tP=RP_w+t

这里的R,tR,t为相机外参,表示世界坐标系到相机坐标系的变换


畸变

由于镜头透镜等原因等,图形成像存在畸变(广角、鱼眼)

假设像素离光心的距离为rr,连线与水平轴夹角为θ\theta

真实坐标为(xt,yt)(x_t,y_t),畸变图像坐标为(x,y)(x,y)

径向畸变(与rr有关):

xt=x(1+k1r2+k2r4+k3r6)x_t =x(1+k_1r^2+k_2r^4+k_3r^6)

yt=y(1+k1r2+k2r4+k3r6)y_t =y(1+k_1r^2+k_2r^4+k_3r^6)

切向畸变(与θ\theta有关):可以理解为成像平面不完全垂直

xt=x+2p1xy+p2(r2+2x2)x_t = x+2p_1xy+p_2(r^2+2x^2)

yt=y+2p2xy+p1(r2+2y2)y_t = y+2p_2xy+p_1(r^2+2y^2)

整合结果为:

xt=x(1+k1r2+k2r4+k3r6)+2p1xy+p2(r2+2x2)x_t =x(1+k_1r^2+k_2r^4+k_3r^6)+2p_1xy+p_2(r^2+2x^2)

yt=y(1+k1r2+k2r4+k3r6)+2p2xy+p1(r2+2y2)y_t =y(1+k_1r^2+k_2r^4+k_3r^6)+2p_2xy+p_1(r^2+2y^2)

畸变参数在标定中获得


总结

1.已知世界坐标系下一点PwP_w

2.通过R,tR,t变换到相机坐标系P=RPw+tP=RP_w+t

3.将PP点转换到归一化平面Z=1Z=1(像素坐标系)中,Pc=1ZPP_c = \frac{1}{Z}P

4.将PcP_c做畸变处理获得PctP_{ct}

5.将PctP_{ct}通过内参KK转换获得像素坐标(u,v)(u,v)[uv1]=KPct\begin{bmatrix} u \\ v \\ 1\end{bmatrix} = KP_{ct}


双目

假设两个相机共面平行摆放,

假设空间中一点在左相机的坐标为(ul,vl)(u_l,v_l),在左相机的坐标为(ur,vr)(u_r,v_r)

两相机光心距离(基线)bb,焦距为ff

则有:

zfz=bul+urb\frac{z-f}{z}=\frac{b-u_l+u_r}{b}

整理可得z=fbulurz=\frac{fb}{u_l-u_r}

其中uluru_l-u_r被称为视差dd

视差最小为一个像素,所以双目可测的最大距离为fbfb


RGBD

物理手段获得图像深度,主要有结构光和TOF两种原理,受光以及被测物体材质影响


代码实现细项

opencv和pcl我都安装过了,所以没有安装过程

注意一下pcl的实现中,CMakeLists中编译要用C++17,不然编译可能报错(或者奇奇怪怪的bug)

参考:http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html


pcl点云图最终效果

pcl_viewer map.pcd

CH6:非线性优化

运动与状态方程

运动方程:xk=f(xk1,uk,wk)x_k=f(x_{k-1},u_k,w_k)

xkx_k表示位置或者位姿,描述当前状态

uku_k表示传感器观测量,描述运动量

wkw_k表示噪声,描述误差

运动方程是描述当前与之前位置的关系


观测方程:zk,j=h(yj,xk,vk,j)z_{k,j}=h(y_j,x_k,v_{k,j})

yjy_j表示路标点,例如世界坐标下一点

xkx_k同上

vk,jv_{k,j}表示噪声

zk,jz_{k,j}表示摄像头观测量

观测方程描述世界坐标中一点与摄像头像素点之间的关系,也就是之前的相机模型

SLAM研究定位与建图,也就对应了xkx_kyjy_j


状态估计问题

以往是用滤波器来求解状态估计,而现在非线性优化成为主流

状态估计可以描述为条件分布P(xz,u)P(x \vert z,u),理解为已知摄像头与自身传感器数据求解当前位置

在视觉SLAM中,考虑只有观测zz的情况,则问题可以简化为P(xz)P(x \vert z),类似与Structure from Motion

由贝叶斯法则可以得:

P(xz)=P(zx)P(x)P(z)P(zx)P(x)P(x \vert z)=\frac{P(z \vert x)P(x)}{P(z)} \propto P(z \vert x)P(x)

P(xz)P(x \vert z)称为后验概率,P(zx)P(z \vert x) 称为似然,P(x)P(x)称为先验

最大后验估计(MAP):求解使得P(zx)P(x)P(z\vert x)P(x)最大对应的xx

最大似然估计(MLE):求解使得P(zx)P(z\vert x)最大对应的xx


举个栗子

假设某次观测zk,j=h(yj,xk)+vk,jz_{k,j}=h(y_j,x_k)+v_{k,j},其中vk,jN(0,Qk,j)v_{k,j} \sim N(0,Q_{k,j}),已知zk,jz_{k,j}估计xk,yjx_k,y_j

所以P(zj,kxk,yj)=N(h(yj,xk),Qk,j)P(z_{j,k} \vert x_k,y_j)=N(h(y_j,x_k),Q_{k,j})

这里涉及到知识,假设X(μ,σ2)X \sim(\mu,\sigma^2),则aX+b(aμ+b,a2σ2)aX+b \sim (a\mu+b,a^2\sigma^2)

而对于高斯分布X(μ,)X \sim(\mu,\sum)

P(x)=1(2π)Ndet()exp(12(xμ)T1(xμ))P(x)=\frac{1}{\sqrt{({2\pi})^Ndet(\sum)}}exp(-\frac{1}{2}({x-\mu})^T\sum {}^{-1}(x-\mu))

取负对数

ln(P(x))=12ln((2π)Ndet())+12(xμ)T1(xμ)-ln(P(x))=\frac{1}{2}ln(({2\pi})^Ndet(\sum))+\frac{1}{2}({x-\mu})^T\sum {}^{-1}(x-\mu)

求解高斯分布最大化相当于求解负对数最小化

而结果包含两项,前一项与xx无关,后一项是一个二次型

所以最终相当于求解使得(xμ)T1(xμ)({x-\mu})^T\sum {}^{-1}(x-\mu)最小对应的xx

x=argmin((zk,jh(yj,xk))TQk,j1(zk,jh(yj,xk)))x^* =argmin(({z_{k,j}-h(y_j,x_k)})^TQ_{k,j}^{-1}(z_{k,j}-h(y_j,x_k)))

而求解式子是个二次型,也被称为最小二乘

二次型复习一下,一般形式:

f(x1,x2,,xn)=a11x12+a22x22++annxn2+2a12x1x2+2a13x1x3++2a(n1)nxn1xnf(x_1,x_2,\cdot,x_n)=a_{11}x_1^2+a_{22}x_2^2+\cdot \cdot\cdot+a_{nn}x_n^2+2a_{12}x_1x_2+2a_{13}x_1x_3+\cdot \cdot \cdot+2a_{(n-1)n}x_{n-1}x_n

而二次型可以写成矩阵的形式,例如

ax2+2bxy+cy2ax^2+2bxy+cy^2可以写成[xy][abbc][xy]=XTAX\begin{bmatrix} x&y\end{bmatrix}\begin{bmatrix} a&b\\b&c\end{bmatrix}\begin{bmatrix} x\\y\end{bmatrix}=X^TAX


一般化

对于一般化问题

xk=f(xk1,uk,wk)x_k=f(x_{k-1},u_k,w_k)

zk,j=h(yj,xk,vk,j)z_{k,j}=h(y_j,x_k,v_{k,j})

定义运动误差和观测误差,也就是当前值减期望值

ev,k=xkf(xk1,uk)e_{v,k}=x_k-f(x_{k-1},u_k)

ey,j,k=zk,jh(xk,yj)e_{y,j,k}=z_{k,j}-h(x_k,y_j)

上述栗子只有考虑观测方程,类比上述栗子结果形式,并求和可得最小化函数

J(x)=kev,kTRk1ev,k+kjey,k,jTQk,j1ey,k,jJ(x)=\sum_ke_{v,k}^TR_k^{-1}e_{v,k}+\sum_k\sum_je_{y,k,j}^TQ_{k,j}^{-1}e_{y,k,j}

即求解使得J(x)J(x)最小对应的x,yx,y


求解非线性最小二乘

对于任意函数f(x)f(x),求解xx使得12f(x)22\frac{1}{2} {\vert \vert f(x) \vert \vert_2}^2最小

df(x)dx=0\frac{df(x)}{dx}=0易求,找出极值点和鞍点(一方向是极大值,一方向是极小值),对比即可获得最值点

一般地,df(x)dx=0\frac{df(x)}{dx}=0难求,采用迭代方式求解


迭代方式:

1.给定初始值x0x_0

2.寻找增量Δxk\Delta x_k,使得12f(x+Δxk)22\frac{1}{2}{\vert \vert f(x+\Delta x_k )\vert \vert_2}^2达到极小值

3.满足终止条件(Δxk\Delta x_k够小),停止

4.不满足终止条件,xk+1=xk+Δxkx_{k+1}=x_k+\Delta x_k


确定Δxk\Delta x_k,对目标函数泰勒展开

f(x+Δx)22f(x)22+J(x)Δx+12ΔxHΔxT+{\vert \vert f(x+\Delta x) \vert \vert_2}^2 \approx {\vert \vert f(x) \vert \vert_2}^2+J(x)\Delta x+\frac{1}{2}\Delta xH\Delta x^T+\cdot \cdot \cdot

若取一阶:

Δx\Delta x取负梯度方向Δx=JT(x)\Delta x^*=-J^T(x),给定步长迭代。

其中J(x)J(x)为雅克比矩阵,该方法称为最速下降法

存在zigzag问题(过于贪婪),迭代次数多

若取二阶:

另目标函数对Δx\Delta x的导数为0,可得HΔx=JT(x)H \Delta x=-J^T(x)

其中HH称为海塞矩阵,该方法称为牛顿法

需要计算复杂的海塞矩阵


即采用二阶,又不需要计算海塞的方法:

1.Gauss-Newton

一阶近似f(x)f(x)f(x+Δx)f(x)+J(x)Δxf(x+\Delta x) \approx f(x)+J(x)\Delta x

带入目标函数12f(x+Δx)22\frac{1}{2}{\vert \vert f(x+\Delta x )\vert \vert_2}^2,令对Δx\Delta x的导数为0,化简可得

JT(x)J(x)Δx=JT(x)f(x)J^T(x)J(x)\Delta x=-J^T(x)f(x)

所以对于迭代时的xkx_k,只需要计算J(xk)J(x_k)f(xk)f(x_k)即可求得Δx\Delta x

但是没有办法保证JT(x)J(x)J^T(x)J(x)可逆

2.Levenberg-Marquadt

该方法一定程度保证高斯牛顿的方程可解

LM方法属于信赖区域方法,认为近似只在区域内可靠

对于一阶近似:f(x+Δx)f(x)+J(x)Δxf(x+\Delta x) \approx f(x)+J(x)\Delta x

定义近似程度描述:ρ=f(x+Δx)f(x)J(x)Δx\rho = \frac{f(x+\Delta x)-f(x)}{J(x)\Delta x},表示 实际下降/近似下降

ρ\rho太小,说明近似多了,需要减小近似范围

ρ\rho太大,说明近似少了,需要增大近似范围

所以相当于在高斯牛顿法基础上,增加了区域约束

minΔx12f(xk)+J(xk)Δxk2,DΔxk2μ\min_{\Delta x} \frac{1}{2} {\vert\vert f(x_k)+J(x_k)\Delta x_k \vert\vert}^2, {\vert\vert D\Delta x_k \vert\vert}^2 \leq \mu

其中Levenberg令DDII,Marquadt令DD为非负对角阵

利用Lagrange乘子转化为无约束,得最小化函数

12f(xk)+J(xk)Δxk2+λ2DΔxk2 \frac{1}{2} {\vert\vert f(x_k)+J(x_k)\Delta x_k \vert\vert}^2+\frac{\lambda}{2} {\vert\vert D\Delta x_k \vert\vert}^2

同样展开化简,令对Δx\Delta x的导数为0,得

(JT(x)J(x)+λDTD)Δx=JT(x)f(x)(J^T(x)J(x)+\lambda D^TD)\Delta x=-J^T(x)f(x)

可以理解为在JT(x)J(x)J^T(x)J(x)的基础上加了一个矩阵,一定程度增强了正定性

对于方程的理解,可以看出二阶和一阶的结合,λ\lambda控制一阶权重


总结

LM求解非线性最小二乘的方法:

对于任意函数f(x)f(x),求解xx使得12f(x)22\frac{1}{2} {\vert \vert f(x) \vert \vert_2}^2最小

1.给定初始值x0x_0,以及信赖区域半径μ\mu

2.对于第kk次迭代,求解Δxk\Delta x_k

(JT(xk)J(xk)+λDTD)Δxk=JT(xk)f(xk)(J^T(x_k)J(x_k)+\lambda D^TD)\Delta x_k=-J^T(x_k)f(x_k)

3.计算ρ=f(x+Δx)f(x)J(x)Δx\rho= \frac{f(x+\Delta x)-f(x)}{J(x)\Delta x}μ={2μ,ρ>340.5μ,ρ<14\mu =\left\{\begin{matrix} 2\mu,&\rho>\frac{3}{4} \\0.5\mu,&\rho<\frac{1}{4}\end{matrix}\right.

4.若ρ\rho大于某阈值,认为近似可行,xk+1=xk+Δxkx_{k+1}=x_k+\Delta x_k

5.判断算法是否收敛,不收敛则返回2,收敛则结束


代码实现细项

CERES安装

Google Ceres Solver是通用最小二乘问题求解库

安装参考官网教程:http://www.ceres-solver.org/installation.html

# 先参考官网安装依赖 

# 安装
git clone https://github.com/ceres-solver/ceres-solver.git
cd ceres-solver/
mkdir ceres-bin
cd ceres-bin
cmake .. # 可能会卡在 Detected Ceres being used as a git submodule
make
make test
sudo make install

# 测试
bin/simple_bundle_adjuster ../data/problem-16-22106-pre.txt

CERES注意事项

ceres需要借助源码中提供的CeresConfig.cmake.in文件帮忙找到库

该文件在ceres-solver/cmake中

在项目目录下创建一个cmake_modules文件夹,把该文件放在其中

CMakeLists.txt中添加以下字句即可

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)

但是我使用的时候不需要这一步也可以成功编译


G2O安装

g2o是图优化库,安装参考:https://zhuanlan.zhihu.com/p/363025399


G2O注意事项

g2o的使用需要注意几个问题

1.CMakeLists.txt中c++版本要14,编译模式是Release,不然编译不通过

2.课程所给代码编译会报错,部分指针需要转换成智能指针unique_ptr

3.g2o需要借助源码中提供的FindG2O.cmake文件帮忙找到库,在g2o/cmake_modules


最后用python画图如下


CH7:视觉里程计1

ORB

特征点的特点:1.可重复性 2.可区分性 3.提取高效 4.跟图像局部相关

描述子:特征点周围的图像信息,用于区分不同特征点


关键点Oriented FAST

FAST:一个像素点周围一圈nn个像素点中有连续mm个像素点比该像素点高一个阈值则认为是关键点,可利用图像金字塔解决尺度问题,常在后续添加非极大值抑制等筛选操作。

Oriented FAST:在FAST基础上计算了旋转,特征的旋转是由灰度质心法实现的。

灰度质心法实现如下:

对于图像块BB,定义图像块的矩为:mpq=x,yBxpyqI(x,y),p,q={0,1}m_{pq}=\sum_{x,y \in B}x^py^qI(x,y),\,\,\, p,q=\{0,1\}

通过矩找到图像块的质心:C=(m10m00,m01m00)C=(\frac{m_{10}}{m_{00}},\frac{m_{01}}{m_{00}})

质心CC与图像块中心OO的组成的向量OC\vec{OC},它的方向定义为特征点的方向θ=atan(m01m10)\theta=atan(\frac{m_{01}}{m_{10}})


描述子BRIEF

BRIEF是一种二进制描述,在特征点附近的多次像素比较。

以BRIEF-128为例

假设pattern为

{[(Δx11,Δy11),(Δx21,Δy21)],[(Δx12,Δy12),(Δx22,Δy22)],,[(Δx1n,Δy1n),(Δx2n,Δy2n)]}n=128\{ [(\Delta x_{1}^1,\Delta y_{1}^1),(\Delta x_{2}^1,\Delta y_{2}^1)],[(\Delta x_{1}^2,\Delta y_{1}^2),(\Delta x_{2}^2,\Delta y_{2}^2)],\cdot\cdot\cdot,[(\Delta x_{1}^n,\Delta y_{1}^n),(\Delta x_{2}^n,\Delta y_{2}^n)] \}_{n=128}

则它的BRIEF由128位组成,每一位为{1I(x+Δx1n,y+Δy1n)>I(x+Δx2n,y+Δy2n)0I(x+Δx1n,y+Δy1n)I(x+Δx2n,y+Δy2n)\left\{\begin{matrix} 1 &I(x+\Delta x_{1}^n,y+\Delta y_{1}^n)>I(x+\Delta x_{2}^n,y+\Delta y_{2}^n)\\0&I(x+\Delta x_{1}^n,y+\Delta y_{1}^n)\leq I(x+\Delta x_{2}^n,y+\Delta y_{2}^n)\end{matrix}\right.

ORB中采用旋转之后的BRIEF,比较特征点的描述子,需要用到汉明距离。


特征匹配

通过描述子的差异判断是否为同一点

方法右:暴力匹配,快速最近邻(FLANN)等


对极几何

对极约束

特征匹配后,只有两个单目图像中特征点之间的对应关系,可以求解两相机之间的旋转和平移,2D-2D

下图反应的是同一个点在两个图像之间的对应关系

其中pp是空间点,p1,p2p_1,p_2分别是点在图像I1I_1和图像I2I_2上的位置

O1,O2O_1,O_2代表图像I1I_1和图像I2I_2的光心,e1,e2e_1,e_2为极点

p1e1p_1e_1PO2PO_2在图像I1I_1上的投影,p2e2p_2e_2PO1PO_1在图像I1I_1上的投影

我们现在已知p1,p2p_1,p_2,求解空间点PP以及两个相机之间的变换T12T_{12}

T12T_{12}分解为R,tR,t,有:s1p1=KP,s2p2=K(RP+t)s_1p_1=KP,s_2p_2=K(RP+t)

使用归一化坐标并去掉内参x1=K1p1,x2=K1p2x_1=K^{-1}p_1,x_2=K^{-1}p_2x2=Rx1+tx_2=Rx_1+t

两边左乘t^t\hat{}消掉ttt^x2=t^Rx1t\hat{}x_2=t\hat{}Rx_1

两边再左乘x2Tx_2^Tx2Tt^x2=x2Tt^Rx1x_2^Tt\hat{}x_2=x_2^Tt\hat{}Rx_1

左式为x2T(t×x2)x_2^T \cdot (t \times x_2),一个向量和与自己垂直的向量相乘,结果为0

故可得对极约束:x2Tt^Rx1=0x_2^Tt\hat{}Rx_1=0

表示为带内参的形式为p2T(K1)Tt^RK1p1=0p_2^T{(K^{-1}})^Tt\hat{}RK^{-1}p_1=0


求解R,t,PR,t,P

定义Essential矩阵:E=t^RE=t\hat{}R,Fundamental矩阵:F=(K1)TEK1F={(K^{-1}})^TEK^{-1}

EE矩阵的定义来看,EE有6个自由度,减去一个任意长度自由度,故有5个,存在内部约束

EE矩阵的3*3矩阵来看,EE有9个自由度,减去一个任意长度自由度,故有8个

常用八点法计算EE

假设E=[e1e2e3e4e5e6e7e8e9]E=\begin{bmatrix} e_1&e_2&e_3 \\e_4&e_5&e_6\\e_7&e_8&e_9\end{bmatrix},设e=[e1,e2,,e9]Te=[e_1,e_2,\cdot\cdot\cdot,e_9]^T,则

对于已知一对匹配点有:[u11v111]E[u21v211]=0\begin{bmatrix} u_{1}^1&v_{1}^1&1\end{bmatrix} E\begin{bmatrix} u_{2}^1\\v_{2}^1\\1\end{bmatrix}=0

展开化简得:[u11u21,u11v21,u11,v11u21,v11v21,v11,u21,v21,1]e=0[u_{1}^1u_{2}^1,u_{1}^1v_{2}^1,u_{1}^1,v_{1}^1u_{2}^1,v_{1}^1v_{2}^1,v_{1}^1,u_{2}^1,v_{2}^1,1]e=0(视频中少写了一项)

故八点法为:

[u11u21,u11v21,u11,v11u21,v11v21,v11,u21,v21,1u12u22,u12v22,u12,v12u22,v12v22,v12,u22,v22,1 u18u28,u18v28,u18,v18u28,v18v28,v18,u28,v28,1]e=0\begin{bmatrix} u_{1}^1u_{2}^1,u_{1}^1v_{2}^1,u_{1}^1,v_{1}^1u_{2}^1,v_{1}^1v_{2}^1,v_{1}^1,u_{2}^1,v_{2}^1,1\\ u_{1}^2u_{2}^2,u_{1}^2v_{2}^2,u_{1}^2,v_{1}^2u_{2}^2,v_{1}^2v_{2}^2,v_{1}^2,u_{2}^2,v_{2}^2,1\\\ \cdot\cdot\cdot \\ u_{1}^8u_{2}^8,u_{1}^8v_{2}^8,u_{1}^8,v_{1}^8u_{2}^8,v_{1}^8v_{2}^8,v_{1}^8,u_{2}^8,v_{2}^8,1\end{bmatrix}e=0

求解EE后可以求解R,tR,tE=t^RE=t\hat{}R

EE进行SVD奇异值分解,得到E=UVTE=U\sum V^T

t1^=URZ(π2)UT\hat{t_1}=UR_Z(\frac{\pi}{2})\sum U^T

t2^=URZ(π2)UT\hat{t_2}=UR_Z(-\frac{\pi}{2})\sum U^T

R1=URZT(π2)VTR_1=UR_Z^T(\frac{\pi}{2})V^T

R2=URZT(π2)VTR_2=UR_Z^T(-\frac{\pi}{2})V^T

求出四组解,通过深度为正得到真正的解。

八点法常用在单目SLAM初始化,多于八对点时,用最小二乘或者RANSAC

八点法存在的问题:尺度不确定性、纯旋转问题无法求解

八点法在特征点共面时(俯视仰视)会退化,常用单应矩阵,设特征点位于某平面nTPd=1-\frac{n^TP}{d}=1解决。H=K(RtnTd)K1H=K(R-\frac{tn^T}{d})K^{-1}


求解完R,tR,t可以通过三角化求解PP

对于s1x1=s2Rx2+ts_1x_1=s_2Rx_2+t,已知R,t,x1,x2R,t,x_1,x_2求解s1,s2s_1,s_2

求解s2s_2则左乘x1^\hat{x_1},消掉s1s_1,求解s1s_1同理

或者直接求[Rx2x1][s2s1]=t\begin{bmatrix}-Rx_2&x_1\end{bmatrix}\begin{bmatrix}s_2\\s_1\end{bmatrix}=t的最小二乘解


三角化存在的问题:

解得的深度的质量与平移有关,而平移太大可能导致特征匹配不成功


Pnp

Pnp是已知3D点的空间位置以及在相机上的投影点,求解相机到世界的旋转和平移的方法,3D-2D。


DLT

假设世界坐标下一点PW=[X,Y,Z,1]P_W=[X,Y,Z,1],转换到相机坐标为RPW+tRP_W+t

假设投影点为x=[u,v,1]x=[u,v,1],则sx=RPW+tsx=RP_W+t

展开

s[uv1]=[r1r2r3t1r4r5r6t2r7r8r9t3][XYZ1]s\begin{bmatrix}u \\v \\1\end{bmatrix}=\begin{bmatrix}r_1&r_2&r_3&t_1 \\r_4&r_5&r_6&t_2 \\r_7&r_8&r_9&t_3\end{bmatrix}\begin{bmatrix}X \\Y \\Z\\1\end{bmatrix}

最下一行s=[r7,r8,r9,t3][X,Y,Z,1]Ts=[r_7,r_8,r_9,t_3][X,Y,Z,1]^T,带入可以消去ss

k1=[r1,r2,r3,t1]T,k2=[r4,r5,r6,t2]T,k3=[r7,r8,r9,t3]Tk_1=[r_1,r_2,r_3,t_1]^T,k_2=[r_4,r_5,r_6,t_2]^T,k_3=[r_7,r_8,r_9,t_3]^T

k1TPk3TPu=0,k2TPk3TPv=0k_1^TP-k_3^TPu=0,k_2^TP-k_3^TPv=0

所以对于一对对应点xn=[un,vn,1],Pn=[Xn,Yn,Zn,1]Tx_n=[u_n,v_n,1],P_n=[X_n,Y_n,Z_n,1]^T

可以有两个方程

k1TPnk3TPnun=0k_1^TP_n-k_3^TP_nu_n=0

k2TPnk3TPnvn=0k_2^TP_n-k_3^TP_nv_n=0

方程含有12个未知数,至少需要6对点,超过6对点用最小二乘法

该方法忽略旋转矩阵内在约束,故在求解后需要投影回SO(3)SO(3),常用QR分解实现


P3P

P3P需要用到4对匹配点,3对用于计算,1对用于验证

如上图,已知Δabc\Delta abc在相机坐标系的位置,ΔABC\Delta ABC在世界坐标下的位置

我们需要求解出ΔABC\Delta ABC在相机坐标系下的位置,将PnPPnP问题转化为ICPICP问题

由相似可得

OA2+OB22OAOBcos(a,b)=AB2OA^2+OB^2-2OA\cdot OBcos(a,b)=AB^2

OB2+OC22OBOCcos(b,c)=BC2OB^2+OC^2-2OB\cdot OCcos(b,c)=BC^2

OA2+OC22OAOCcos(a,c)=AC2OA^2+OC^2-2OA\cdot OCcos(a,c)=AC^2

三式除以OC2OC^2,记x=OAOC,y=OBOCx=\frac{OA}{OC},y=\frac{OB}{OC},得

x2+y22xycos(a,b)=AB2OC2x^2+y^2-2xycos(a,b)=\frac{AB^2}{OC^2}

x2+12ycos(b,c)=BC2OC2x^2+1-2ycos(b,c)=\frac{BC^2}{OC^2}

x2+12xcos(a,c)=AC2OC2x^2+1-2xcos(a,c)=\frac{AC^2}{OC^2}

v=AB2OC2,u=BC2AB2,w=AC2AB2v=\frac{AB^2}{OC^2},u=\frac{BC^2}{AB^2},w=\frac{AC^2}{AB^2},得

x2+y22xycos(a,b)=vx^2+y^2-2xycos(a,b)=v

x2+12ycos(b,c)uv=0x^2+1-2ycos(b,c)-uv=0

x2+12xcos(a,c)wv=0x^2+1-2xcos(a,c)-wv=0

把第一式带入下面两个式子得

x2+12ycos(b,c)u(x2+y22xycos(a,b))=0x^2+1-2ycos(b,c)-u(x^2+y^2-2xycos(a,b))=0

x2+12xcos(a,c)w(x2+y22xycos(a,b))=0x^2+1-2xcos(a,c)-w(x^2+y^2-2xycos(a,b))=0

其中cos,u,wcos,u,w均已知,是关于x,yx,y的二元二次方程,用吴氏消元法可解x,yx,y

故我们解得ΔABC\Delta ABC在相机坐标系下的位置


P3P缺点:多于3对匹配点难以处理、没法处理误匹配


Bundle Adjustment

Bundle Adjustment是PnP的一种优化解法

投影关系表示为李代数:su=Kexp(ξ^)Psu=Kexp(\xi \hat{})P

ei=ui1siKexp(ξ^)Pie_i =u_i-\frac{1}{s_i}Kexp(\xi\hat{})P_iuiu_i为重投影

定义重投影误差ξ=argmin(12i=1nui1siKexp(ξ^)Pi22)\xi^*=argmin(\frac{1}{2}\sum^n_{i=1}{\vert\vert u_i-\frac{1}{s_i}Kexp(\xi\hat{})P_i\vert\vert_2}^2)

eδξ=limδξ0e(δξ+ξ)δξ=ePPδξ\frac{\partial e}{\partial \delta\xi}=\lim_{\delta\xi \rightarrow 0}\frac{e(\delta\xi+\xi)}{\delta\xi}=\frac{\partial e}{\partial P'}\frac{\partial P'}{\partial \delta \xi}P=exp(ξ^)PP'=exp(\xi\hat{})P

先求eP\frac{\partial e}{\partial P'}

eP=[uXuYuZvXvYvZ]\frac{\partial e}{\partial P'}=-\begin{bmatrix} \frac{\partial u}{\partial X'}&\frac{\partial u}{\partial Y'}&\frac{\partial u}{\partial Z'}\\\frac{\partial v}{\partial X'}&\frac{\partial v}{\partial Y'}&\frac{\partial v}{\partial Z'}\end{bmatrix}

u=fxXZ+cx,v=fyYZ+cyu= f_x \frac{X'}{Z'}+c_x ,v = f_y \frac{Y'}{Z'}+c_y

eP=[fxZ0fxXZ20fyZfyYZ2]\frac{\partial e}{\partial P'}=-\begin{bmatrix}\frac{f_x}{Z'}&0&-\frac{f_xX'}{Z'^2}\\0&\frac{f_y}{Z'}&-\frac{f_yY'}{Z'^2}\end{bmatrix}

再求Pδξ\frac{\partial P'}{\partial \delta \xi}

对于SE(3)SE(3)ξ\xi为小量,pp为变换点,T=[Rt01]T=\begin{bmatrix} R & t \\ 0 &1\end{bmatrix}

扰动模型:(Tp)ξ=[I(Rp+t)^0T0T]\frac{\partial (Tp)}{\partial \xi} =\begin{bmatrix} I & -(Rp+t) \hat{} \\ 0^T & 0 ^T \end{bmatrix}

这里PP'只有三维,故Pδξ=[I,P^]=[1000ZY010Z0X001YX0]\frac{\partial P'}{\partial \delta \xi}=[I , -P'\hat{}]=\begin{bmatrix}1&0&0&0&Z'&-Y' \\0&1&0&-Z'&0&X'\\0&0&1&Y'&-X'&0\end{bmatrix}

相乘整合可得

eδξ=ePPδξ=[fxZ0fxXZ2fxXYZ2fx+fxX2Z2fxYZ0fyZfyYZ2fyfyY2Z2fyXYZ2fyXZ]\frac{\partial e}{\partial \delta\xi}=\frac{\partial e}{\partial P'}\frac{\partial P'}{\partial \delta \xi}=-\begin{bmatrix} \frac{f_x}{Z'}&0&-\frac{f_xX'}{Z'^2}&-\frac{f_xX'Y'}{Z'^2}&f_x+\frac{f_xX'^2}{Z'^2}&-\frac{f_xY'}{Z'} \\ 0&\frac{f_y}{Z'}&-\frac{f_yY'}{Z'^2}&-f_y-\frac{f_yY'^2}{Z'^2}&\frac{f_yX'Y'}{Z'^2}&\frac{f_yX'}{Z'}\end{bmatrix}

同理可以对PP求偏导,eP=[fxZ0fxXZ20fyZfyYZ2]R\frac{\partial e}{\partial P}=-\begin{bmatrix}\frac{f_x}{Z'}&0&-\frac{f_xX'}{Z'^2}\\0&\frac{f_y}{Z'}&-\frac{f_yY'}{Z'^2}\end{bmatrix}R


ICP

常用于RGBD相机,3D-3D

假设已知空间中一些点在相机一的坐标为P={p1,p2,,pn}P=\{p_1,p_2,\cdot\cdot\cdot,p_n\}

同样的点在相机二的坐标为P={p1,p2,,pn}P'=\{p_1',p_2',\cdot\cdot\cdot,p_n'\}

那么它们之间满足P=RP+tP=RP'+t

定义误差项ei=pi(Rpi+t)e_i=p_i-(Rp_i'+t)

故有最小二乘问题minR,tJ=12i=1npi(Rpi+t)22\min_{R,t} \, J=\frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-(Rp_i'+t)\vert\vert_2}^2

定义质心:p=1ni=1npi,p=1ni=1npip=\frac{1}{n}\sum_{i=1}^np_i,p'=\frac{1}{n}\sum_{i=1}^np_i'

故可以修改目标函数如下:

J=12i=1npi(Rpi+t)+(pp)+(RpRp)2=12i=1npip(RpiRp)+(pRpt)2=12i=1npip(RpiRp)2+(pRpt)2J=\frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-(Rp_i'+t)+(p-p)+(Rp'-Rp')\vert\vert}^2 \\ = \frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-p-(Rp_i'-Rp')+(p-Rp'-t)\vert\vert}^2 \\ =\frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-p-(Rp_i'-Rp')\vert\vert^2+\vert\vert(p-Rp'-t)\vert\vert}^2

其中平方和展开交叉相乘项为0,JJ的表达式变成两式相加,左边与RR有关,右边与R,tR,t有关

采取解的方式为最小化左边项获得RR,然后另右边项为0解出tt

故需要求解minRR=12i=1npip(RpiRp)2\min_R \, R^*=\frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-p-(Rp_i'-Rp')\vert\vert}^2

定义去质心坐标:qi=pip,qi=pipq_i=p_i-p,q_i'=p_i'-p'

故可以修改目标函数如下:

R=12i=1npip(RpiRp)2=12i=1nqiRqi2=12i=1nqiTqi+qiTRTRqi2qiTRqiR^*=\frac{1}{2}\sum_{i=1}^n{\vert\vert p_i-p-(Rp_i'-Rp')\vert\vert}^2 \\ =\frac{1}{2}\sum_{i=1}^n{\vert\vert q_i-Rq_i'\vert\vert}^2\\ =\frac{1}{2}\sum_{i=1}^n{q_i^Tq_i+q_i'^TR^TRq_i'-2q_i^TRq_i'}

只有最后一项与RR有关

i=1nqiTRqi=i=1ntr(RqiqiT)=tr(Ri=1nqiqiT)-\sum_{i=1}^nq_i^TRq_i'=-\sum_{i=1}^ntr(Rq_i'q_i^T)=-tr(R\sum_{i=1}^nq_i'q_i^T)

可以通过SVD求解

W=i=1nqiqiTW=\sum_{i=1}^nq_iq_i'^T的奇异值分解UVTU\sum V^T,则R=UVTR=UV^T

求完RR,可解t=pRpt=p-Rp'


同理,ICP也可以通过非线性优化求解

eδξ=ePPδξ=IPδξ=I[I,P^]=[1000ZY010Z0X001YX0]\frac{\partial e}{\partial \delta\xi}=\frac{\partial e}{\partial P'}\frac{\partial P'}{\partial \delta \xi}=-I\frac{\partial P'}{\partial \delta \xi}=-I[I , -P'\hat{}]=\begin{bmatrix}-1&0&0&0&-Z'&Y' \\0&-1&0&Z'&0&-X'\\0&0&-1&-Y'&X'&0\end{bmatrix}


CH8:视觉里程计2

光流法

稀疏光流以LK光流为代表,稠密光流以HS光流为代表

实际就是通过光流的方法找到匹配点


假设在tt时刻位于(x,y)(x,y)处的像素点的灰度值为I(x,y,t)I(x,y,t)

t+Δtt+\Delta t时刻位于(x+Δx,y+Δy)(x+\Delta x,y+\Delta y)处的像素点的灰度值为I(x+Δx,y+Δy,t+Δt)I(x+\Delta x,y+\Delta y,t+\Delta t)

由灰度不变性可得I(x,y,t)=I(x+Δx,y+Δy,t+Δt)I(x,y,t) = I(x+\Delta x,y+\Delta y,t+\Delta t)

泰勒展开I(x+Δx,y+Δy,t+Δt)I(x,y,t)+Ixdx+Iydy+ItdtI(x+\Delta x,y+\Delta y,t+\Delta t) \approx I(x,y,t)+\frac{\partial I}{\partial x}dx+\frac{\partial I}{\partial y}dy+\frac{\partial I}{\partial t}dt

所以Ixdx+Iydy+Itdt=0\frac{\partial I}{\partial x}dx+\frac{\partial I}{\partial y}dy+\frac{\partial I}{\partial t}dt = 0,所以Ixdxdt+Iydydt=It\frac{\partial I}{\partial x}\frac{dx}{dt}+\frac{\partial I}{\partial y}\frac{dy}{dt}=-\frac{\partial I}{\partial t}

其中Ix,Iy,It\frac{\partial I}{\partial x},\frac{\partial I}{\partial y},-\frac{\partial I}{\partial t}已知,dxdt,dydt\frac{dx}{dt},\frac{dy}{dt}待求,是个二元一次方程组,我们需要多组点求解

常取假设一个窗口W×WW \times W内光度不变,用这些点来求解

Ix=Ix,Iy=Iy,It=It,dxdt=u,dydt=v\frac{\partial I}{\partial x}=I_x,\frac{\partial I}{\partial y}=I_y,\frac{\partial I}{\partial t}=I_t,\frac{dx}{dt}=u,\frac{dy}{dt}=v

则有[Ix1,Iy1Ix2,Iy2Ixn,Iyn][uv]=[It1It2Itn]\begin{bmatrix} I_x^1,I_y^1\\I_x^2,I_y^2 \\ \cdot\cdot\cdot \\I_x^n,I_y^n\end{bmatrix}\begin{bmatrix} u\\ v\end{bmatrix}=\begin{bmatrix}-I_t^1\\-I_t^2\\ \cdot\cdot\cdot\\-I_t^n\end{bmatrix},记为A[uv]=bA\begin{bmatrix}u\\v\end{bmatrix}=b

[uv]=(ATA)1ATb\begin{bmatrix}u\\v\end{bmatrix}^* = -(A^TA)^{-1}A^Tb


直接法

光流法没有用到相机本身的几何结构,没有考虑相机的旋转而缩放,而直接法考虑了这些信息

假设空间中一点PP,在第一帧的投影点为p1p_1,在第二帧的投影点为p2p_2

假设第一帧到第二帧的初始估计为R,tR,t

则有p1=1Z1KP,p2=1Z2K(RP+t)=1Z2Kexp(ξ^)Pp_1=\frac{1}{Z_1}KP,p_2=\frac{1}{Z_2}K(RP+t)=\frac{1}{Z_2}Kexp(\xi\hat{})P

定义光度误差e=I1(p1)I2(p2)e=I_1(p_1)-I_2(p_2)

故有最小二乘问题minξJ=i=1NeiTei\min_{\xi} \, J=\sum_{i=1}^Ne_i^Te_i

根据扰动模型得

e(ξδξ)=I1(1Z1KP)I2(1Z2Kexp(δξ^)exp(ξ^)P)I1(1Z1KP)I2(1Z2K(1+δξ^)exp(ξ^)P)=I1(1Z1KP)I2(1Z2Kexp(ξ^)P+1Z2Kδξ^exp(ξ^)P)e(\xi \, \oplus \delta\xi)=I_1(\frac{1}{Z_1}KP)-I_2(\frac{1}{Z_2}Kexp(\delta\xi\hat{})exp(\xi\hat{})P) \\ \approx I_1(\frac{1}{Z_1}KP)-I_2(\frac{1}{Z_2}K(1+\delta\xi\hat{})exp(\xi\hat{})P)\\ =I_1(\frac{1}{Z_1}KP)-I_2(\frac{1}{Z_2}Kexp(\xi\hat{})P+\frac{1}{Z_2}K\delta\xi\hat{}exp(\xi\hat{})P)\\

q=δξ^exp(ξ^)P,u=1Z2Kqq =\delta\xi\hat{}exp(\xi\hat{})P,u=\frac{1}{Z_2}Kq,则

e(ξδξ)=I1(1Z1KP)I2(1Z2Kexp(ξ^)P+u)=I1(1Z1KP)I2(1Z2Kexp(ξ^)P)I2uuqqδξδξ=e(ξ)I2uuqqδξδξe(\xi \, \oplus \delta\xi) =I_1(\frac{1}{Z_1}KP)-I_2(\frac{1}{Z_2}Kexp(\xi\hat{})P+u) \\ =I_1(\frac{1}{Z_1}KP)-I_2(\frac{1}{Z_2}Kexp(\xi\hat{})P)-\frac{\partial I_2}{\partial u} \frac{\partial u}{\partial q} \frac{\partial q}{\partial \delta \xi}\delta\xi \\ =e(\xi)-\frac{\partial I_2}{\partial u} \frac{\partial u}{\partial q} \frac{\partial q}{\partial \delta \xi}\delta\xi

其中

I2u\frac{\partial I_2}{\partial u} 表示坐标在图像的梯度,uq\frac{\partial u}{\partial q} 表示像素点对投影点的导数,qδξ\frac{\partial q}{\partial \delta \xi} 表示投影点对位姿的导数

uδξ\frac{\partial u}{\partial \delta \xi}参考ch7重投影误差求导,故雅克比为

J=I2uuδξ=I2u[fxZ0fxXZ2fxXYZ2fx+fxX2Z2fxYZ0fyZfyYZ2fyfyY2Z2fyXYZ2fyXZ]J=-\frac{\partial I_2}{\partial u}\frac{\partial u}{\partial \delta \xi}=-\frac{\partial I_2}{\partial u}\begin{bmatrix} \frac{f_x}{Z}&0&-\frac{f_xX}{Z^2}&-\frac{f_xXY}{Z^2}&f_x+\frac{f_xX^2}{Z^2}&-\frac{f_xY}{Z} \\ 0&\frac{f_y}{Z}&-\frac{f_yY}{Z^2}&-f_y-\frac{f_yY^2}{Z^2}&\frac{f_yXY}{Z^2}&\frac{f_yX}{Z}\end{bmatrix}

补充一点双线性插值

如图,我们已知四个相邻的像素点P1,P2,P3,P4P_1,P_2,P_3,P_4对应的像素

现在估算浮点数坐标PP对应的像素

先算PP'PP''的像素

Δx=xx1,Δy=yy1\Delta x =x-x_1,\Delta y = y-y_1

I(P)ΔxI(P2)+(1Δx)I(P1)I(P') \approx\Delta xI(P_2)+(1-\Delta x)I(P_1)

I(P)ΔxI(P4)+(1Δx)I(P3)I(P'') \approx\Delta xI(P_4)+(1-\Delta x)I(P_3)

I(P)ΔyI(P)+(1Δy)I(P)I(P) \approx\Delta y I(P'')+(1-\Delta y)I(P') \\

所以

I(P)=Δy[ΔxI(P4)+(1Δx)I(P3)]+(1Δy)[ΔxI(P2)+(1Δx)I(P1)]I(P) =\Delta y[\Delta xI(P_4)+(1-\Delta x)I(P_3)]+ (1-\Delta y)[\Delta xI(P_2)+(1-\Delta x)I(P_1)] \\

整理得

I(P)=(1Δx)(1Δy)I(P1)+Δx(1Δy)I(P2)+(1Δx)(Δy)I(P3)+ΔxΔyI(P4)I(P)=(1-\Delta x)(1-\Delta y)I(P_1)+\Delta x(1-\Delta y)I(P_2)+(1-\Delta x)(\Delta y)I(P_3)+\Delta x\Delta yI(P_4)


CH9:视觉里程计项目实践

代码实现细项

安装viz

viz可以用于位姿可视化

先检查opencv的modules目录下有没有viz文件夹

没有的话下载对应OpenCV版本的opencv_contrib并解压,比如我是4.5.0

网址:https://github.com/opencv/opencv_contrib/tags

sudo apt-get install libvtk6-dev # 依赖 不同ubuntu版本不同
cp -r opencv_contrib-4.5.0/modules/viz/ opencv-4.5.0/modules/  # 拷贝 我们只需要其中的viz
cd opencv-4.5.0/build
cmake -DWITH_VTK=ON ..
make
sudo make install

之前opencv3时使用viz不需要额外引入头文件

换用opencv4使用时需要包含opencv2/viz.hpp


数据集:http://vision.in.tum.de/data/datasets/rgbd-dataset/download


CH10:后端1(全局地图优化)

EKF式后端(渐进式)

KF推导

对于运动方程和观测方程:

xk=f(xk1,uk)+wkx_k=f(x_{k-1},u_k)+w_k

zk,j=h(yj,xk)+vk,jz_{k,j}=h(y_j,x_k)+v_{k,j}

我们将kk时刻所有待估计的量记作Tk{xk,y1,...,ym}T_k\triangleq \{x_k,y_1,...,y_m\}TT既包含了xx也包含了yy

则运动方程和观测方程化简为:

Tk=f(Tk1,uk)+wkT_k = f(T_{k-1},u_k)+w_k

zk=h(Tk)+vkz_k = h(T_k)+v_k

我们需要估计的当前状态为P(TkT0,u1:k,z1k)P(T_k \vert T_0,u_{1:k},z_{1:k})

根据贝叶斯公式P(AB)=P(BA)P(A)P(B)P(A \vert B) = \frac{P(B \vert A) P(A)}{P(B)},可得P(TkT0,u1:k,z1:k)P(zkTk)P(TkT0,u1:k,z1:k1)P(T_k \vert T_0,u_{1:k},z_{1:k}) \propto P(z_k \vert T_k) P(T_k \vert T_0,u_{1:k},z_{1:k-1})

其中P(zkTk)P(z_k \vert T_k)为似然,P(TkT0,u1:k,z1:k1)P(T_k \vert T_0,u_{1:k},z_{1:k-1})为先验,观测方程已知,似然已知,只需求先验

对先验进行展开:

P(TkT0,u1:k,z1:k1)=P(TkTk1,T0,u1:k,z1:k1)P(Tk1T0,u1:k,z1:k1)dTk1P(T_k \vert T_0,u_{1:k},z_{1:k-1})= \int P(T_k \vert T_{k-1},T_0,u_{1:k},z_{1:k-1})P(T_{k-1} \vert T_0,u_{1:k},z_{1:k-1})dT_{k-1}

假设kk时刻状态只和k1k-1时刻有关(一阶马尔可夫性),则:

P(TkT0,u1:k,z1:k1)=P(TkTk1,uk)P(Tk1T0,u1:k1,z1:k1)dTk1P(T_k \vert T_0,u_{1:k},z_{1:k-1})= \int P(T_k \vert T_{k-1},u_k)P(T_{k-1} \vert T_0,u_{1:k-1},z_{1:k-1})dT_{k-1}

上述第一项消去了k1k-1时刻之前的量,第二项消去uku_k是因为考虑kk时刻的uku_kk1k-1时刻无关

对比一下可以发现,左侧是kk时刻的状态分布,右侧第一项是运动分布,第二项是k1k-1时刻的状态分布


假设是一个线性系统,且噪声满足方差不变的正态分布,即:

Tk=AkTk1+uk+wk,wkN(0,R)T_k=A_k T_{k-1} + u_k+w_k \, , \, w_k \sim N(0,R)

zk=CkTk+vk,vkN(0,Q)z_k=C_k T_k+v_k \, , \, v_k \sim N(0,Q)

仅通过运动方程推出的称为先验,表示为Tkˉ\bar {T_k}

经过观测方程后得到的称为后验,表示为Tk^\hat{T_k}

卡尔曼滤波要实现的就是:已知k1k-1时刻的后验,通过kk时刻的观测和输入,确定kk时刻的后验

① 从k1k-1时刻的后验到kk时刻的先验的过程称为预测

假设后验到真实值满足高斯分布:Tk1N(T^k1,^k1)T_{k-1} \sim N(\hat{T}_{k-1},\hat{\sum}_{k-1})\sum为协方差矩阵,则第一步通过运动方程预测可得:

Tˉk=AkTk1+uk+wk=AkN(T^k1,^k1)+N(uk,0)+N(0,R)N(AkT^k1+uk,Ak^k1AkT+R)\bar{T}_k = A_k T_{k-1} + u_k+w_k = A_k N(\hat{T}_{k-1},\hat{\sum}_{k-1})+N(u_k,0)+N(0,R) \sim N(A_k\hat{T}_{k-1}+u_k,A_k \hat{\sum}_{k-1}A_k^{T}+R)

这里涉及到知识,假设XN(μ,σ2)X \sim N(\mu,\sigma^2),则aX+bN(aμ+b,a2σ2)aX+b \sim N(a\mu+b,a^2\sigma^2)

所以kk时刻Tˉk=AkT^k1+uk,ˉk=Ak^k1AkT+R\bar{T}_k = A_k\hat{T}_{k-1}+u_k \, , \, \bar{\sum}_{k} = A_k \hat{\sum}_{k-1}A_k^{T}+R

② 从kk时刻的先验到kk时刻的后验的过程称为更新

由观测方程zk=CkTk+vkz_k=C_k T_k+v_k可得P(zkTk)=N(CkTk,Q)P(z_k \vert T_k) = N(C_kT_k,Q)

对于上述推出的关系P(TkT0,u1:k,z1:k)P(zkTk)P(TkT0,u1:k,z1:k1)P(T_k \vert T_0,u_{1:k},z_{1:k}) \propto P(z_k \vert T_k) P(T_k \vert T_0,u_{1:k},z_{1:k-1}),将先验后验带入可得

N(T^k,^k)N(CkTk,Q)N(Tˉk,ˉk)N(\hat{T}_k,\hat{\sum}_{k}) \propto N(C_kT_k,Q) N(\bar{T}_k,\bar{\sum}_{k})

上述正比关系,式子两侧相差一个系数,两个正态分布相乘,结果是一个正态分布乘以一个系数,

而这两个系数不会影响到指数项,故从指数项下手求解

对于正态分布N(μ1,σ12)N \sim(\mu_1,\sigma_1^2),我们只需要关注化简后的指数项(xμ1)2(σ12)1(x-\mu_1)^2(\sigma_1^2)^{-1}

f(x)=12πσ1e(xμ1)22σ12=12πσ1e12(xμ1)2(σ12)1f(x) =\frac{1}{\sqrt{2\pi}\sigma_1}e^{-\frac{(x-\mu_1)^2}{2\sigma_1^2} } = \frac{1}{\sqrt{2\pi}\sigma_1}e^{-\frac{1}{2}{(x-\mu_1)^2}{(\sigma_1^2)^{-1}} }

对于矩阵正态分布N(X,)N \sim (X,\sum)\sum为对称阵,即只需关注(xX)T1(xX)(x-X)^T\sum^{-1}(x-X)

将上述代入可得:

(TkT^k)T^k1(TkT^k)=(zkCkTk)TQ1(zkCkTk)+(TkTˉk)Tˉk1(TkTˉk)(T_k-\hat{T}_k)^T \hat{\sum}_{k}^{-1}(T_k-\hat{T}_k) = (z_k-C_k T_k)^T Q^{-1}(z_k-C_k T_k) + (T_k-\bar{T}_k)^T \bar{\sum}_{k}^{-1}(T_k-\bar{T}_k)

对于TkT_k的二次项系数,有:

^k1=CkTQ1Ck+ˉk1\hat{\sum}_{k}^{-1} = C_k^TQ^{-1}C_k+ \bar{\sum}_{k}^{-1}

对于TkT_k的一次项系数,有:

T^kT^k1=zkTQ1Ck+TˉkTˉk1\hat{T}_k^T\hat{\sum}_{k}^{-1} =z_k^TQ^{-1}C_k+ \bar{T}_k^T\bar{\sum}_{k}^{-1}

去转置得:

^k1T^k=CkTQ1zk+ˉk1Tˉk\hat{\sum}_{k}^{-1} \hat{T}_k = C_k^TQ^{-1}z_k+ \bar{\sum}_{k}^{-1} \bar{T}_k

②式左右同时左乘^k\hat{\sum}_{k}得:

T^k=^kCkTQ1zk+^kˉk1Tˉk\hat{T}_k = \hat{\sum}_{k} C_k^TQ^{-1}z_k+ \hat{\sum}_{k} \bar{\sum}_{k}^{-1} \bar{T}_k

定义K=^kCkTQ1K=\hat{\sum}_{k} C_k^TQ^{-1}得:

T^k=Kzk+^kˉk1Tˉk\hat{T}_k = K z_k+ \hat{\sum}_{k} \bar{\sum}_{k}^{-1} \bar{T}_k

根据①消去ˉk1\bar{\sum}_{k}^{-1}得:

T^k=Kzk+^k(^k1CkTQ1Ck)Tˉk=Kzk+(IKCk)Tˉk=Tˉk+K(zkCkTˉk)\hat{T}_k = K z_k+ \hat{\sum}_{k} (\hat{\sum}_{k}^{-1} - C_k^TQ^{-1}C_k) \bar{T}_k = K z_k + (I-KC_k) \bar{T}_k = \bar{T}_k + K(z_k-C_k \bar{T}_k)

算完T^k\hat{T}_k回过头算一下^k\hat{\sum}_{k}

对于①式左右同时左乘^k\hat{\sum}_{k}得:

I=^kCkTQ1Ck+^kˉk1=KCk+^kˉk1I = \hat{\sum}_{k} C_k^TQ^{-1}C_k+ \hat{\sum}_{k} \bar{\sum}_{k}^{-1} = KC_k + \hat{\sum}_{k} \bar{\sum}_{k}^{-1}

整理一下有^k=(IKCk)ˉk\hat{\sum}_{k} =(I-KC_k)\bar{\sum}_{k}

最后最后还要整理一下卡尔曼增益KK

^k=(IKCk)ˉk\hat{\sum}_{k} =(I-KC_k)\bar{\sum}_{k} 代入K=^kCkTQ1K=\hat{\sum}_{k} C_k^TQ^{-1}得:K=((IKCk)ˉk)CkTQ1K = ((I-KC_k)\bar{\sum}_{k}) C_k^T Q^{-1}

右乘QQKQ=(IKCk)ˉkCkTK Q = (I-K C_k) \bar{ \sum }_{k} C_k^T

KK整到一块得:K=ˉkCkT(CkˉkCkT+Q)1K = \bar{\sum}_{k} C_k^T {(C_k \bar{\sum}_{k} C_k^T + Q)}^{-1}

KF总结

对于线性系统:

Tk=AkTk1+uk+wk,wkN(0,R)T_k=A_k T_{k-1} + u_k+w_k \, , \, w_k \sim N(0,R)

zk=CkTk+vk,vkN(0,Q)z_k=C_k T_k+v_k \, , \, v_k \sim N(0,Q)

后验到真实值满足高斯分布:Tk1N(T^k1,^k1)T_{k-1} \sim N(\hat{T}_{k-1},\hat{\sum}_{k-1})

预测:

Tˉk=AkT^k1+uk\bar{T}_k = A_k\hat{T}_{k-1}+u_k

ˉk=Ak^k1AkT+R\bar{\sum}_k = A_k \hat{\sum}_{k-1} A_k^{T}+R

更新:

K=ˉkCkT(CkˉkCkT+Q)1K = \bar{\sum}_{k} C_k^T {(C_k \bar{\sum}_{k} C_k^T + Q)}^{-1}

T^k=Tˉk+K(zkCkTˉk)\hat{T}_k = \bar{T}_k + K(z_k-C_k \bar{T}_k)

^k=(IKCk)ˉk\hat{\sum}_{k} =(I-KC_k)\bar{\sum}_{k}

EKF总结

对于非线性系统

Tk=f(Tk1,uk)+wkT_k = f(T_{k-1},u_k)+w_k

zk=h(Tk)+vkz_k = h(T_k)+v_k

一般将运动方程和观测方程在工作点附近进行一阶泰勒展开,近似线性,即:

Tkf(T^k1,uk)+fTk1T^k1(Tk1T^k1)+wk=f(T^k1,uk)+F(Tk1T^k1)+wkT_k \approx f(\hat{T}_{k-1},u_k)+ \frac{\partial f}{\partial T_{k-1}} |_{\hat{T}_{k-1}} (T_{k-1} - \hat{T}_{k-1}) + w_k = f(\hat{T}_{k-1},u_k)+ F (T_{k-1} - \hat{T}_{k-1}) + w_k

zkh(Tˉk)+hTkTˉk(TkTˉk)+vk=h(Tˉk)+H(TkTˉk)+vkz_k \approx h(\bar{T}_k)+\frac{\partial h}{\partial T_k} |_{\bar{T}_k} (T_k - \bar{T}_k) +v_k = h(\bar{T}_k)+H(T_k - \bar{T}_k) +v_k

同理可推导

预测:

Tˉk=f(T^k1,uk)\bar{T}_{k} = f( \hat{T}_{k-1}, u_k)

ˉk=F^k1FT+R\bar{\sum}_k = F \hat{\sum}_{k-1} F^{T}+R

更新:

K=ˉkHT(HˉkHT+Q)1K = \bar{\sum}_{k} H^T {(H \bar{\sum}_{k} H^T + Q)}^{-1}

T^k=Tˉk+K(zkh(Tˉk))\hat{T}_k = \bar{T}_k + K(z_k-h(\bar{T}_k) )

^k=(IKH)ˉk\hat{\sum}_{k} =(I-KH)\bar{\sum}_{k}

优缺点

优点:适用性强,常用于多传感器融合

缺点:一阶马尔可夫性过于简单、数据有离散点可能会发散


BA式后端(批量式)

目前视觉SLAM 主流为非线性优化方法,不假设马尔可夫性,即考虑 kk时刻状态与之前所有状态的关系。

求解推导

假设世界坐标系下一点pp,转到相机坐标P=Rp+t=[X,Y,Z]TP'=Rp+t = [X',Y',Z']^T

PP'归一化得,Pc=[uc,vc,1]T=[XZ,YZ,1]TP_c =[u_c,v_c,1]^T = [\frac{X'}{Z'},\frac{Y'}{Z'},1]^T

去径向畸变得,uc=uc(1+k1rc2+k2rc4),vc=vc(1+k1rc2+k2rc4),rc2=uc2+vc2u_c'=u_c(1+k_1 r_c^2+k_2 r_c^4) \, , \, v_c'=v_c(1+k_1 r_c^2+k_2 r_c^4) \, , \, r_c^2 =u_c^2 +v_c^2

通过内参计算像素得,us=fxuc+cx,vs=fyvc+cyu_s = f_x u_c'+c_x \, , \, v_s =f_y v_c'+c_y

上述过程其实就是由世界坐标pp到像素坐标[us,xs]T[u_s,x_s]^T的观测方程,记为z=[us,vs]T=h(ξ,p)z = [u_s,v_s]^T = h(\xi,p)ξ\xi为外参R,tR,t对应的李代数

故我们可以定义误差S=12ijzijh(ξi,pj)TS = \frac{1}{2}\sum_{i}\sum_{j} {\vert\vert z_{ij}-h(\xi_i,p_j)\vert\vert}^T

将待优化的量定义在一起x=[ξ1,...,ξm,pi,...,pn]Tx = [\xi_1,...,\xi_m,p_i,...,p_n]^T

给自变量一个增量,12f(x+Δx)T12ijzijh(ξi,pj)+FijΔξi+EijΔpjT\frac{1}{2} {\vert\vert f(x+\Delta x) \vert\vert}^T \approx \frac{1}{2}\sum_{i}\sum_{j} {\vert\vert z_{ij}-h(\xi_i,p_j) +F_{ij}\Delta \xi_i +E_{ij}\Delta p_j \vert\vert}^T

其中FijF_{ij}表示对相机姿态的偏导数,Fij=eδξ=[fxZ0fxXZ2fxXYZ2fx+fxX2Z2fxYZ0fyZfyYZ2fyfyY2Z2fyXYZ2fyXZ]F_{ij} = \frac{\partial e}{\partial \delta \xi} = -\begin{bmatrix} \frac{f_x}{Z'}&0&-\frac{f_xX'}{Z'^2}&-\frac{f_xX'Y'}{Z'^2}&f_x+\frac{f_xX'^2}{Z'^2}&-\frac{f_xY'}{Z'} \\ 0&\frac{f_y}{Z'}&-\frac{f_yY'}{Z'^2}&-f_y-\frac{f_yY'^2}{Z'^2}&\frac{f_yX'Y'}{Z'^2}&\frac{f_yX'}{Z'}\end{bmatrix}

EijE_{ij}表示对路标点位置的偏导,Eij=eP=[fxZ0fxXZ20fyZfyYZ2]RE_{ij}=\frac{\partial e}{\partial P}= -\begin{bmatrix} \frac{f_x}{Z'} & 0 & -\frac{f_x X'}{Z'^2} \\ 0 & \frac{f_y}{Z'} &-\frac{f_y Y'}{Z'^2} \end{bmatrix} R

为了把式子写得更整体而不是各项和,将位姿放在一起xc=[ξ1,ξ2,...,ξm]TR6m×1x_c=[\xi_1,\xi_2,...,\xi_m]^T \in R^{6m \times 1},把路标点放一起xp=[p1,p2,...,pn]TR3n×1x_p =[p_1,p_2,...,p_n]^T \in R^{3n \times 1}

则有,12f(x+Δx)T=12e+FΔxc+EΔxpT\frac{1}{2} {\vert\vert f(x+\Delta x) \vert\vert}^T = \frac{1}{2}{\vert\vert e +F\Delta x_c +E\Delta x_p \vert\vert}^T,其中F=[F1,F2,...,Fm]R2×6m,E=[E1.E2,...,En]R2×3nF=[F_1,F_2,...,F_m] \in R^{2 \times 6m}, E = [E_1.E_2,...,E_n] \in R^{2 \times 3n}

求解非线性最小二乘,最终都会要计算增量方程HΔx=gH \Delta x = g

对于GN法,JT(x)J(x)Δx=gJ^T(x)J(x)\Delta x = g

其中J=[FE]R2×(6m+3n),JT=[FTET]R(6m+3n)×2,H=JTJ=[FTFFTEETFETE]R(6m+3n)×(6m+3n)J =\begin{bmatrix}F&E \end{bmatrix} \in R^{2 \times(6m+3n)},J^T= \begin{bmatrix}F^T \\E^T \end{bmatrix} \in R^{(6m+3n) \times 2}, H = J^TJ=\begin{bmatrix}F^TF & F^TE \\ E^T F& E^TE \end{bmatrix} \in R^{(6m+3n) \times (6m+3n)}

由于路标点数量nn大,这里的HH的维度很大,如果直接求逆,会十分消耗计算资源

由于HH存在稀疏性,一般会对其进行边缘化


稀疏性和边缘化

稀疏,简单来讲就是矩阵里有很多元素是0,

HH的稀疏性是由于雅可比J(x)J(x)引起的,

Jij(x)=(02×6,...02×6,eijξi,...02×6,02×6,02×3,...02×3,eijpj,...02×3,02×3)J_{ij}(x)=(0_{2\times6},...0_{2\times6},\frac{\partial e_{ij}}{\partial \xi_i},...0_{2\times6},0_{2\times6},0_{2\times3},...0_{2\times3},\frac{\partial e_{ij}}{\partial p_j},...0_{2\times3},0_{2\times3})

在位姿ξi\xi_i处看到路标点pjp_j,所以除了i,ji,j处其余均为0项,这个误差项具有稀疏性,给HH的贡献也具有稀疏性

对于整体的HHH=i,jJijTJijH=\sum_{i,j}J_{ij}^TJ_{ij}

某个位姿观测到了某个路标点,对应HH矩阵中的非零块,对应图优化的一条边,

HH矩阵形像一个箭头,称为箭头形矩阵,也像一把镐头,也称为镐形矩阵。

我们可以对其Schur消元,在SLAM研究中也称为Marginalization(边缘化)

我们假设H=[BEETC]H = \begin{bmatrix}B&E \\ E^T & C \end{bmatrix}BBCC都是对角阵,BB只和位姿有关,CC只和路标点有关

HΔx=gH \Delta x = g可以写成[BEETC][ΔxcΔxp]=[vw]\begin{bmatrix}B&E \\ E^T & C \end{bmatrix} \begin{bmatrix} \Delta x_c \\ \Delta x_p\end{bmatrix} = \begin{bmatrix} v \\ w\end{bmatrix}

高斯消元[IEC10I][BEETC][ΔxcΔxp]=[IEC10I][vw]\begin{bmatrix}I&-EC^{-1} \\ 0 & I \end{bmatrix} \begin{bmatrix}B&E \\ E^T & C \end{bmatrix} \begin{bmatrix} \Delta x_c \\ \Delta x_p\end{bmatrix} = \begin{bmatrix}I&-EC^{-1} \\ 0 & I \end{bmatrix}\begin{bmatrix} v \\ w\end{bmatrix}

化简得[BEC1ET0ETC][ΔxcΔxp]=[vEC1ww]\begin{bmatrix}B-EC^{-1}E^T & 0 \\ E^T & C \end{bmatrix} \begin{bmatrix} \Delta x_c \\ \Delta x_p\end{bmatrix} = \begin{bmatrix} v-EC^{-1}w \\ w\end{bmatrix}

这样第一行方程组就与Δxp\Delta x_p无关,即[BEC1ET]Δxc=vEC1w[B-EC^{-1}E^T]\Delta x_c = v-EC^{-1}w

我们可以先通过这个方程组解出Δxc\Delta x_c,然后代入第二行方程组ETΔxc+CΔxp=wE^T \Delta x_c + C \Delta x_p =w求解Δxp\Delta x_p

因为路标点的维度比较大,这样做可以加速求解,而且CC矩阵是对角阵,求逆易解

从概率的角度来讲,我们实际上把求 (Δxc,Δxp)(\Delta x_c,\Delta x_p)的问题,转化成先求Δxc\Delta x_c,再求Δxp\Delta x_p的过程,

相当于进行了条件概率展开P(xc,xp)=P(xc)P(xpxc)P(x_c,x_p)=P(x_c)P(x_p\vert x_c),结果是求出了关于xcx_c的边缘分布,故称边缘化

鲁棒核函数

为了避免某个误差项导致整个优化朝错误的方向进行,可以采用核函数

核函数可以保证优化的每条边的误差不会太大以掩盖掉其他的边

具体的做法是把原先误差的二范数度量,替换成一个增长较慢的函数,同时自身又要光滑可导

以常用的Huber核为例

H(e)={12e2,eδδ(e12δ),otherwiseH(e) =\left\{\begin{matrix} \frac{1}{2}e^2,&\vert e \vert \le \delta \\ \delta(\vert e\vert -\frac{1}{2}\delta),&otherwise\end{matrix}\right.

实际上就是将误差太大时的二次增长改成一次增长


代码实现细项

安装Meshlab

直接命令行安装即可

sudo apt-get install meshlab

打开时颜色会比较暗,在右侧把shading改成None就可以了


数据集:https://grail.cs.washington.edu/projects/bal/index.html


CH11:后端2(位姿图优化)

全局图优化有个缺点,就是机器人运行的越久,地图越来越大

全局图优化会非常耗时,而这其中占主要部分的是特征点优化

但经过若干次观测之后,收敛的特征点的空间位置估计就会收敛至一个值保持不动

花费大量计算资源计算再对这些特征点进行优化是不明智的,

所以一般在优化几次之后就把特征点固定住,只对位姿进行优化


位姿图优化原理

在Pose Graph图优化中

节点是相机位姿,我们表示为ξ1,ξ2,...,ξn\xi_1,\xi_2,...,\xi_n

边是两个位姿节点之间相对运动的估计,记ξi\xi_iξj\xi_j之间的运动为Δξij\Delta \xi_{ij}

按照李群的写法为:ΔTij=Ti1Tj\Delta T_{ij}=T_i^{-1}T_j,写成李代数为:Δξij=ln(exp((ξi)^)exp(ξj^))ˇ\Delta \xi_{ij} =ln(exp((-\xi_i)\hat{})exp(\xi_j\hat{}))\check{}

ΔTij\Delta T_{ij}移到右边,并定义误差项,eij=ln(ΔTij1Ti1Tj)ˇ=ln(exp((ξij)^)exp((ξi)^)exp(ξj^))ˇe_{ij} = ln(\Delta T_{ij}^{-1}T_i^{-1}T_j)\check{} = ln(exp((-\xi_{ij})\hat{})exp((-\xi_{i})\hat{})exp(\xi_j\hat{}))\check{}

ξi\xi_iξj\xi_j各一个左扰动δξi\delta\xi_iδξj\delta\xi_jeij^=ln(Tij1Ti1exp((δξi)^)exp(δξj^)Tj)ˇ\hat{e_{ij}} = ln(T_{ij}^{-1}T_i^{-1}exp((-\delta\xi_i)\hat{})exp(\delta\xi_j\hat{})T_j)\check{}

为了将扰动项移到右侧(或左侧),需要用到伴随性质:Texp(ξ^)T1=exp((Ad(T)ξ)^),Ad(T)=[Rt^0R]Texp(\xi\hat{})T^{-1}=exp((Ad(T)\xi)\hat{}) \,\, ,\,\,Ad(T)=\begin{bmatrix}R & t\hat{} \\ 0 & R \end{bmatrix}

TT改成T1T^{-1}得:T1exp(ξ^)T=exp((Ad(T1)ξ)^)T^{-1}exp(\xi\hat{})T=exp((Ad(T^{-1})\xi)\hat{}),左乘TTexp(ξ^)T=Texp((Ad(T1)ξ)^)exp(\xi\hat{})T=Texp((Ad(T^{-1})\xi)\hat{})

所以我们可以通过上式实现TTexpexp的位置交换

利用上式子,可以将扰动项移至最右

eij^=ln(Tij1Ti1exp((δξi)^)exp(δξj^)Tj)ˇ=ln(Tij1Ti1exp((δξi)^)Tjexp((Ad(Tj1)δξj)^))ˇ=ln(Tij1Ti1Tjexp((Ad(Tj1)(δξi))^)exp((Ad(Tj1)δξj)^))ˇ\hat{e_{ij}} = ln(T_{ij}^{-1}T_i^{-1}exp((-\delta\xi_i)\hat{})exp(\delta\xi_j\hat{})T_j)\check{} \\ =ln(T_{ij}^{-1}T_i^{-1}exp((-\delta\xi_i)\hat{})T_jexp((Ad(T_j^{-1})\delta\xi_j)\hat{}))\check{} \\ =ln(T_{ij}^{-1}T_i^{-1}T_jexp((Ad(T_j^{-1})(-\delta\xi_i))\hat{})exp((Ad(T_j^{-1})\delta\xi_j)\hat{}))\check{}

利用BCH近似exp(ξ^)exp(Δξ^)exp((Jr1Δξ+ξ)^)exp(\xi\hat{})exp(\Delta\xi\hat{}) \approx exp((\mathcal{J}_r^{-1}\Delta\xi+\xi)\hat{}),可得

eij^=ln(Tij1Ti1Tjexp((Ad(Tj1)(δξi))^)exp((Ad(Tj1)δξj)^))ˇ=ln(Tij1Ti1exp(ξj^)exp((Ad(Tj1)(δξi))^)exp((Ad(Tj1)δξj)^))ˇln(Tij1Ti1exp((Jr1Ad(Tj1)δξi+ξj)^)exp((Ad(Tj1)δξj)^))ˇln(Tij1Ti1exp(Jr1Ad(Tj1)δξjJr1Ad(Tj1)δξi+ξj))ˇ=ln(exp(ξij^)exp(ξi^)exp(Jr1Ad(Tj1)δξjJr1Ad(Tj1)δξi+ξj))ˇ\hat{e_{ij}} = ln(T_{ij}^{-1}T_i^{-1}T_jexp((Ad(T_j^{-1})(-\delta\xi_i))\hat{})exp((Ad(T_j^{-1})\delta\xi_j)\hat{}))\check{} \\ = ln(T_{ij}^{-1}T_i^{-1}exp(\xi_j\hat{})exp((Ad(T_j^{-1})(-\delta\xi_i))\hat{})exp((Ad(T_j^{-1})\delta\xi_j)\hat{}))\check{} \\ \approx ln(T_{ij}^{-1}T_i^{-1}exp((-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\xi_j)\hat{})exp((Ad(T_j^{-1})\delta\xi_j)\hat{}))\check{} \\ \approx ln(T_{ij}^{-1}T_i^{-1}exp(\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\xi_j))\check{} \\ =ln(exp(-\xi_{ij}\hat{})exp(-\xi_i\hat{})exp(\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\xi_j))\check{}

通过BCH近似ln(exp(A)exp(B))=A+B+12[A,B]+112[A,[A,B]]112[B,[A,B]]+...A+Bln(exp(A)exp(B)) = A + B +\frac{1}{2}[A,B]+\frac{1}{12}[A,[A,B]]-\frac{1}{12}[B,[A,B]]+... \approx A + B,得

eij^ln(exp(ξij^)exp(ξi^)exp(Jr1Ad(Tj1)δξjJr1Ad(Tj1)δξi+ξj))ˇln(exp(ξjξijξiJr1Ad(Tj1)δξi+Jr1Ad(Tj1)δξj)^)ˇ=ξjξijξiJr1Ad(Tj1)δξi+Jr1Ad(Tj1)δξj=eijJr1Ad(Tj1)δξi+Jr1Ad(Tj1)δξj\hat{e_{ij}} \approx ln(exp(-\xi_{ij}\hat{})exp(-\xi_i\hat{})exp(\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\xi_j))\check{} \\ \approx ln(exp(\xi_j-\xi_{ij}-\xi_i-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j)\hat{})\check{} \\ = \xi_j-\xi_{ij}-\xi_i-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j \\ =e_{ij}-\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_i+\mathcal{J}_r^{-1}Ad(T_j^{-1})\delta\xi_j

其中Jr1(eij)I+12[ϕe^ρe^0ϕe^]\mathcal{J}_r^{-1}(e_{ij}) \approx I + \frac{1}{2}\begin{bmatrix}\hat{\phi_e} & \hat{\rho_e} \\ 0 & \hat{\phi_e}\end{bmatrix}

ε\varepsilon为所有边的集合,则总体目标函数T=minξ12i,jε(ei,jTij1eij)T=\min_{\xi}\frac{1}{2}\sum_{i,j \in \varepsilon}(e_{i,j}^T\sum_{ij}^{-1}e_{ij})


代码实现细项

安装g2o_viewer

可以看到在g2o/g2o/apps下是有g2o_viewer的,但是没有可执行文件

原因是缺失依赖,g2o_viewer没有编译

参考官方README:https://github.com/RainerKuemmerle/g2o

# 安装依赖
sudo apt-get install libsuitesparse-dev
sudo apt-get install qtdeclarative5-dev
sudo apt-get install qt5-qmake
sudo apt-get install libqglviewer-dev-qt5

# 重新编译
cd ~/g2o/build
cmake ..
make
sudo make install
sudo ldconfig

# 动态库链接更新
sudo ldconfig

ceres求解参考

参考:https://blog.csdn.net/weixin_42099090/article/details/106907271

参考:https://blog.csdn.net/u012348774/article/details/84144084

代码参考:https://github.com/qqqGpe/slam14-ch10-ceres

官网文档:http://ceres-solver.org


g2o文件格式
顶点:
VERTEX_SE3:QUAT index px py pz qx qy qz qw
边:
EDGE_SE3:QUAT idfrom idto px py pz qx qy qz qw 信息矩阵上三角

CH12:回环检测

前端会产生累积误差,而后端采用位姿图优化,会导致优化轨迹产生偏移,

回环检测不止关注相邻帧,可以给出一些时隔更久的约束,可以用于消除累积误差,保证全局一致

正确的回环检测可以保证轨迹和地图在长时间下的正确性,就算跟踪算法丢失也可以用于重定位

在某些时候,我们把只有前端和局部后端的系统称为VO,而把带有回环检测和全局后端的系统称为SLAM


回环可以形象的理解为经过了同个(相似的)地方,从某个地方出发后又回到这个地方

我们需要预计哪一个地方可能出现回环,大体为两种思路:基于几何和基于外观

基于几何,简单来讲就是看里程计的值判断是否回到之前的某个位置,但是里程计又存在累积误差,没法用于准确判断

基于外观,简单来讲就是看两个图像的相似性,摆脱了累积误差,成为视觉SLAM中的主流做法


指标

评价检测算法的好坏,书中引出了两个概念:感知偏差和感知变异

感知偏差对应假阳(FP),程序认为是回环,实际上不是回环

感知变异对应假阴(FN),程序认为不是回环,实际上是回环

准确率表示程序认为是回环的所有中事实上是回环的概率:Precision=TPTP+FPPrecision=\frac{TP}{TP+FP}

召回率表示事实上是回环的所有中程序认为是回环的概率:Recall=TPTP+FNRecall=\frac{TP}{TP+FN}

这两者往往存在矛盾,但好的算法在高召回率下也能保持高准确率

条件放严时,检测到的回环少,召回率降低,但是准确率一般会提高

条件放松时,检测到的回环多,召回率升高,但是准确率一般会降低

在SLAM中,我们对准确率要求较为严格,因为错误的回环会导致算法出现严重的错误


词袋模型

检测相似性可以采用词袋的做法。

词袋(Bag-of-Words BoW),目的是用“图像上有哪几种特征”来描述一个图像

由于度量的是“是否存在”,所以比通过灰度判断更加稳定

由于度量的不是“在哪里存在”,对空间位置和排序无关,所以对微小运动不敏感


词袋中会有各种概念,对应到不同单词上,而所有单词组成了字典

直观上理解,这些概念可以是“人,车,狗”等等具象的概念

比如一张图像中有两个人和一辆车,我们就可以用向量[2,1,0]T[2,1,0]^T表示这幅图像,可以用这个向量来量化相似度

但实际上常常是采用较为抽象的概念,例如“概念1,概念2,概念3”

这张图像对于这些概念的出现情况也可以写成一个向量

而这些概念集合,对应到单词集合,组成了字典


字典

回想一下词袋模型,可以概括为一个图像中的特征可以分为几个概念,每个概念的数量是多少

而在图像集中分出这些概念,也就是获取字典的过程,实质上是个聚类的过程,可以用经典的Kmeans解决

对于图像,我们可以将提取的特征点(通过其描述子)聚类成一个含有多个单词的字典

但是这种方式的查找效率不高,常采用kk叉树式字典

假设对于NN个特征点,我们要构建一个深度为dd的,每次分叉为kk的树,实现如下

1.在根节点把所有样本聚成k类
2.对于每一层的每个节点,把属于该节点的样本再聚成k类
3.以此类推,最后获得叶子层,也就是Words

这样子这个树可以容纳kdk^d个单词,即能保证单词丰富,也能保证对数级别的查找时间复杂度


相似度计算

有了字典,我们就可以通过字典中的单词来表示图像,进而计算相似度

对于特定特征fif_i,我们可以找到他对应的单词wjw_j

当查找完所有之后,我们可以获得在字典(所有单词)中,这幅图像所对应的单词分布

上述操作是默认每个词同样重要,但是实际上每个词的重要程度是不一样的

常用的方法是TF-IDF(Term Frequency-Inverse Document Frequency),即译频率-逆文档频率

TF 的思想是,某单词在一个图像中经常出现,它的区分度就高。

IDF 的思想是,某单词在字典中出现的频率越低,则分类图像时区分度越高


对于TF:假设图像中单词wiw_i出现了mim_i次,而单词总共有mm个,则TFi=mimTF_i=\frac{m_i}{m}

对于IDF:假设有nn个特征,单词wiw_i中有nin_i个特征,则IDFi=lognniIDF_i=log\frac{n}{n_i}

于是单词的权重ηi=TFi×IDFi\eta_i=TF_i \times IDF_i

所以对于一个图像,它的特征点可对应到多个单词,组成它的BoW,用ww表示单词,用η\eta表示权重,则有

A=(w1,η1),(w2,η2),...,(wN,ηN)vAA={(w_1,\eta_1),(w_2,\eta_2),...,(w_N,\eta_N)} \triangleq v_A

若采用L1范数,相似度公式表示为:s(vA,vB)=2i(vAi+vBivAivBi)s(v_A,v_B)=2\sum_{i}(\vert v_{Ai}\vert+\vert v_{Bi}\vert-\vert v_{Ai} - v_{Bi}\vert)


CH13:建图

之前接触的的特征点地图,是局部地图,用于定位

但如果有导航,避障,重建等需求,就需要稠密地图

进一步地,如果有交互的需求,可能还需要语义地图

单目求深度

极线搜索与块匹配

稠密深度图估计中,我们不能把每个像素都当做特征点,计算描述子

为了匹配不同图中的像素,我们要用到极线搜索和块匹配

在一个视角中,像素p1p_1对应的空间点分布在一条射线上

在另一个视角中,这条射线的投影形成图像平面上的一条线,这条投影线就是极线

当我们知道两个视角之间的运动时,极线也就可以确定了

所以要找p1p_1的匹配点只需要在极线上搜索就可以了

由于单纯靠单个像素的灰度做匹配十分不稳定,所以采用块匹配技术

p1p_1周围取一个块,然后在极线上也取很多同样大小的像素块进行比较

假设取p1p_1周围的w×ww \times w的小块为AA,在极线上取的nn个小块为BB

我们需要取差值最小的块,存在若干种计算方法(i=1,2,...,w,j=1,2,...,wi=1,2,...,w,\,\,\,j=1,2,...,w):

1.SAD(Sum of Absolute Distance),绝对距离之和,S(A,B)SAD=i,jA(i,j)B(i,j)S(A,B)_{SAD}=\sum_{i,j} \vert A(i,j) - B(i,j)\vert,越近0越好

2.SSD(Sum of Squared Distance),平方距离之和,S(A,B)SSD=i,j(A(i,j)B(i,j))2S(A,B)_{SSD}=\sum_{i,j} ( A(i,j) - B(i,j))^2,越近0越好

3.NCC(Normalized Cross Correlation),归一化相关性,S(A,B)NCC=i,jA(i,j)B(i,j)i,jA(i,j)2i,jB(i,j)2S(A,B)_{NCC}=\frac{\sum_{i,j}A(i,j)B(i,j)}{\sqrt{\sum_{i,j}A(i,j)^2\sum_{i,j}B(i,j)^2}},越近1越好

4.上述方法去均值,允许整体亮度有一个差值


通过上述方法,可以找到匹配的两个点p1,p2p_1,p_2,例如是(u1,v1)(u_1,v_1)(u2,v2)(u_2,v_2)

接下来我们要计算他的深度,假设深度分别是d1d_1d2d_2

得归一化向量f1=1n1[u1cxfxv1cyfy1],f2=1n2[u2cxfxv2cyfy1]f_1 = \frac{1}{n_1}\begin{bmatrix} \frac{u_1-c_x}{f_x} \\ \frac{v_1-c_y}{f_y} \\ 1\end{bmatrix},f_2=\frac{1}{n_2}\begin{bmatrix} \frac{u_2-c_x}{f_x} \\ \frac{v_2-c_y}{f_y} \\ 1\end{bmatrix}

因为P1=RP2+tP_1 = RP_2 +t

则有d1f1=d2Rf2+td_1 f_1 = d_2 R f_2 + t

[f1Tf1f1TRf2f2Tf1f2TRf2][d1d2]=[f1Ttf2Tt]\begin{bmatrix} f_1^Tf_1 & -f_1^TRf_2 \\ f_2^Tf_1 & -f_2^TRf_2\end{bmatrix} \begin{bmatrix} d_1 \\ d_2 \end{bmatrix} = \begin{bmatrix} f_1^Tt \\ f_2^Tt \end{bmatrix}

[a1a2a3a4][d1d2]=[b1b2]\begin{bmatrix} a_1 & a_2 \\ a_3 & a_4\end{bmatrix} \begin{bmatrix} d_1 \\ d_2 \end{bmatrix} = \begin{bmatrix} b_1 \\ b_2 \end{bmatrix}

[d1d2]=1a1a4a2a3[a4a2a3a1][b1b2]\begin{bmatrix} d_1 \\ d_2 \end{bmatrix} = \frac{1}{a_1a_4-a_2a_3}\begin{bmatrix} a_4 & -a_2 \\ -a_3 & a_1\end{bmatrix}\begin{bmatrix} b_1 \\ b_2 \end{bmatrix}

取均值f=d1f1+d2Rf2+t2f= \frac{d_1f_1+d_2Rf_2+t}{2}ff的模即为深度


通过上述计算,一个AA块就会对应算出nnBB块,这些值组合起来就是一个沿着极线的分布

通常情况下,这个分布存在着许多峰值,我们可以取最大的峰值对应的像素点来计算深度

在多帧的情况下,某些错误的峰值可能达到最大,进而导致误匹配,导致计算的深度错误

所以对于估计的深度,往往是采用一个概率分布来描述


高斯分布的深度滤波器

假设深度dd满足的概率分布是高斯分布:P(d)=N(μ,σ2)P(d)=N(\mu,\sigma^2)

假设新计算的深度P(dnow)=N(μnow,σnow2)P(d_{now})=N(\mu_{now},\sigma_{now}^2)

高斯融合后的结果会更可靠,P(dfuse)=N(σnow2μ+σ2μnowσ2+σnow2,σ2σnow2σ2+σnow2)P(d_{fuse})=N(\frac{\sigma_{now}^2\mu+\sigma^2\mu_{now}}{\sigma^2+\sigma_{now}^2},\frac{\sigma^2\sigma_{now}^2}{\sigma^2+\sigma_{now}^2})


μnow\mu_{now}即为计算出的深度,问题是,如何确定σnow2\sigma_{now}^2

假设只考虑由几何关系带来的不确定性

对于下图,O1PO_1 P向量ppO1O2O_1O_2向量tt已知

O2PO_2P向量a=pta=p-t

α=arccosp,t,β=arcosa,t\alpha = arccos\langle p,t\rangle \, , \, \beta=arcos\langle a,-t\rangle

对于向量m1,m2m_1,m_2,向量夹角计算公式有cosθ=m1m2m1m2cos\theta = \frac{m_1 \cdot m_2}{ \vert m_1\vert \vert m_2\vert}

对于p2p_2一个像素误差带来的对于β\beta角的误差δβ=arctan1f\delta\beta=arctan\frac{1}{f}

正弦定理有pt=sinβsin(παβ)=sin(βδβ)sin(παβ+δβ)\frac{\vert\vert p'\vert\vert}{\vert\vert t\vert\vert}=\frac{sin\beta'}{sin(\pi-\alpha-\beta')}=\frac{sin(\beta-\delta\beta)}{sin(\pi-\alpha-\beta+\delta\beta)}

故单个像素的不确定引起的深度不确定性σnow=pp\sigma_{now} = \vert\vert p\vert\vert-\vert\vert p'\vert\vert


深度估计过程可以概括为:

1.假设所有像素满足高斯分布
2.极线搜索找到对应的像素点
3.三角化计算深度和不确定性
4.融合上一次的数据直到收敛

代码实现细项

下载数据集: http://rpg.ifi.uzh.ch/datasets/remode_test_data.zip


讨论

①图像块没有区分度(没有纹理),会导致误匹配

②当像素梯度与极线夹角较小时,极线匹配的不确定性大;夹角较大时,极线匹配的不确定性小。

③深度其实不是很满足高斯分布,现在常常用深度的倒数-逆深度,将逆深度近似为高斯分布更为有效

④如果相机旋转,会导致同一个图像块的相关性为负,所以在块匹配之前,通常要通过仿射变换矩阵,将像素变换后再匹配。


RGBD稠密建图

RGBD相机获得深度简单且可靠,建图也容易


点云地图

点云地图是较为基础的,简单来讲就是每一个点的XYZ,它更接近于传感器读取的原始数据。


八叉树地图

点云地图存在几个问题

①规模太大了,且提供了很多不必要的细节。

②点云地图无法处理运动物体,只有“添加点”,而没有“当点消失时把它移除”


所以有了八叉树地图

把三维空间建模为许多个小方块,每一个小方块可以分成八个小方块,这八个小方块又分别能分成八个小方块,以此类推…

那么,整个从最大空间细分到最小空间的过程,就是一棵八叉树


但是从上述表述中还没法体现看出八叉树地图有什么优势

因为点云地图同样可以做到,只需要用体素滤波限制体素大小和八叉树叶子节点一样大小即可


对于八叉树地图,在节点中会存储它是否被占据的信息

当某个方块的所有子节点都被占据或都不被占据时,就没必要展开这个节点

例如地图为空白时,我们就只需一个根节点,而不需要完整的树

实际的物体经常连在一起,空白的地方也常常会连在一起,所以大多数八叉树节点都无需展开到叶子层面。

所以说,八叉树比点云节省了大量的存储空间

而且有被占据的信息,相当于我们建模了地图中的障碍物信息


节点中存储它是否被占据的信息,这个信息一般我们用概率表示,假设为xx

然后我们引入一个新的变量yy,如果节点被占据,那么让yy增加;反之,让它减小

然后用概率对数值 将yy映射到[0,1][0,1]区间用来表示概率xx,即x=logit1(y)=exp(y)exp(y)+1x = logit^{-1}(y)=\frac{exp(y)}{exp(y)+1}

刚开始yy为0,对应xx为0.5;yy不断增加,xx趋近1;yy不断减小,xx趋近0


所以我们就可以用RGB-D数据,更新八叉树地图了

假设我们观测到某个像素带有深度d,说明这个深度值对应的空间点上观察到了一个占据数据

并且,从相机光心出发,到这个点的线段上,是没有物体的


代码实现细项

官方链接:https://github.com/OctoMap/octomap

看README,好像没有说依赖doxygen,我就没装

要同时编译octomap和octovis,只需要对整个进行编译就好了

git clone https://github.com/OctoMap/octomap.git
cd octomap
mkdir build && cd build
cmake ..
make
sudo make install

CH14:SLAM的现在与未来

目前的发展

MonoSLAM:第一个实时的单目视觉SLAM系统,是通过EKF实现的

PTAM:视觉SLAM首次区分前后端,首次用非线性优化取代EKF,引入关键帧机制,同时是一个增强现实软件

ORB-SLAM:是现代主流的特征点 SLAM 的一个高峰,支持单目,双目,RGBD,回环是亮点

LSD-SLAM:单目直接法,半稠密地图,CPU实时

SVO:稀疏直接法,速度非常快,提出了深度滤波器的概念

RTAB-MAP:RGBD SLAM的一个经典方案


未来

两个大方向:视觉惯导融合和语义SLAM、

其他一些方向:基于线/面特征的SLAM、动态场景下的SLAM、多机器人的 SLAM


完结撒花!!!